У меня есть такой фрейм данных:
data = {
'ID': [1, 1, 2, 1, 2, 1, 1, 2, 2, 2, 1, 2, 2, 1],
'timestamp': pd.date_range(start='1/1/2023', periods=14, freq='D'),
'value': [11, 22, 33, 44, 55, 66, 77, 88, 99, 11, 22, 33, 44, 55]
}
Мой фактический фрейм данных содержит миллионы строк. Я сортирую столбцы временных меток, поэтому столбец идентификатора перемежается, когда вы смотрите на необработанный фрейм данных.
Я хочу сгруппировать по идентификатору и найти разницу между каждой строкой и третьей предыдущей строкой. Сейчас у меня это работает так:
# Sort by ID and timestamp
df = df.sort_values(by=['ID', 'timestamp'])
# Group by 'ID' and calculate the difference with the 5th previous row
df['value_diff'] = df.groupby('ID', group_keys=False)['value'].apply(lambda x: x - x.shift(3))
Однако, поскольку мой фактический фрейм данных огромен, это занимает довольно много времени. Я также читал, что использование лямбды происходит медленно.
В конце концов я хочу фильтровать по тому, увеличивается или уменьшается столбец value_diff.
Обычно я бы использовал
inc_check=df['value'].diff(3).ge(0)
df=df[inc_check]
но он не группируется для расчета разницы.
Есть ли более элегантный способ добиться этого?
@mozway миллионы строк и, возможно, сотни групп






Не используйте apply, просто используйте groupby.shift напрямую, а затем вычтите исходный столбец:
df['value_diff'] = df['value'] - df.groupby('ID')['value'].shift(3)
Или groupby.diff :
df['value_diff'] = df.groupby('ID')['value'].diff(3)
Выход:
ID timestamp value value_diff
0 1 2023-01-01 11 NaN
1 1 2023-01-02 22 NaN
3 1 2023-01-04 44 NaN
5 1 2023-01-06 66 55.0
6 1 2023-01-07 77 55.0
10 1 2023-01-11 22 -22.0
13 1 2023-01-14 55 -11.0
2 2 2023-01-03 33 NaN
4 2 2023-01-05 55 NaN
7 2 2023-01-08 88 NaN
8 2 2023-01-09 99 66.0
9 2 2023-01-10 11 -44.0
11 2 2023-01-12 33 -55.0
12 2 2023-01-13 44 -55.0
Спасибо за это предложение. Я как раз добавлял свой вопрос, когда вы отправили ответ :) Есть ли способ сделать groupby.shift и отфильтровать фрейм данных за один шаг без необходимости создания вычисляемого столбца?
Конечно: out = df[df.groupby('ID')['value'].diff(3).ge(0)] должно помочь
import pandas as pd
import numpy as np
# Sample DataFrame
data = {
'ID': [1, 1, 2, 1, 2, 1, 1, 2, 2, 2, 1, 2, 2, 1],
'timestamp': pd.date_range(start='1/1/2023', periods=14, freq='D'),
'value': [11, 22, 33, 44, 55, 66, 77, 88, 99, 11, 22, 33, 44, 55]
}
df = pd.DataFrame(data)
df = df.sort_values(by=['ID', 'timestamp'])
# Calculate the difference with the 3rd previous row
df['value_diff'] = df.groupby('ID')['value'].diff(3)
df['diff_trend'] = np.where(df['value_diff'] >= 0, 'increasing', 'decreasing')
# Drop rows where value_diff is NaN
df_filtered = df.dropna(subset=['value_diff'])
print(df_filtered)
"""
ID timestamp value value_diff diff_trend
5 1 2023-01-06 66 55.0 increasing
6 1 2023-01-07 77 55.0 increasing
10 1 2023-01-11 22 -22.0 decreasing
13 1 2023-01-14 55 -11.0 decreasing
8 2 2023-01-09 99 66.0 increasing
9 2 2023-01-10 11 -44.0 decreasing
11 2 2023-01-12 33 -55.0 decreasing
12 2 2023-01-13 44 -55.0 decreasing
"""
сколько строк и групп у вас в наборе данных?