首页 > 解决方案 > Pandas 对按另一列分组的行求和

问题描述

我附上了数据集

 Time  podId  Batt (avg)  Temp (avg)
0   2019-10-07   9999         6.1   71.271053
1   2019-10-08   9999         6.0   71.208285
2   2019-10-09   9999         5.9   77.896628
3   2019-10-10   9999         5.8   78.709279
4   2019-10-11   9999         5.7   71.849283
59  2019-12-05   8888         5.5   76.548780
60  2019-12-06   8888         5.4   73.975295
61  2019-12-07   8888         5.3   76.209434
62  2019-12-08   8888         5.2   76.717481
63  2019-12-09   8888         5.1   70.433920

我使用 -batt2 = pd.read_csv('battV2.csv')

  1. 我需要确定何时发生电池更换,即Batt (avg)从前一行增加的时间。我可以通过以这种方式使用“差异”来做到这一点batt2['Vdiff']=batt2['Batt (avg)'].diff(-1)
  2. 现在对于每个podId我需要对Vdiff电池变化之间的列求和,即在两个负值Vdiff之间
  3. 我也需要Temp (avg)在相同的范围内进行平均
  4. 计数Time以确定电池更换之间的天数

谢谢。

标签: pandas-groupby

解决方案


涉及几个步骤:

导入数据

请注意,我已经稍微更改了您的数据集,以便为您的需求提供有效的测试用例(在您给定的数据集中,Batt_avg永远不会增加)。

from io import StringIO
import pandas as pd

data = StringIO('''Time    podId  Batt_avg  Temp_avg
0   2019-10-07   9999         6.1   71.271053
1   2019-10-08   9999         6.0   71.208285
2   2019-10-09   9999         5.9   77.896628
3   2019-10-10   9999         5.8   78.709279
4   2019-10-11   9999         5.7   71.849283
5   2019-10-12   9999         6.0   71.208285
6   2019-10-13   9999         5.9   77.896628
7   2019-10-14   9999         5.8   78.709279
8   2019-10-15   9999         5.7   71.849283
59  2019-12-05   8888         5.5   76.548780
60  2019-12-06   8888         5.4   73.975295
61  2019-12-07   8888         5.3   76.209434
62  2019-12-08   8888         5.2   76.717481
63  2019-12-09   8888         5.1   70.433920''')
df = pd.read_csv(data,  delim_whitespace=True)

确定电池电压的变化

正如您已经发现的那样,您可以使用diff(). 我不确定您给出的代码是否df.Batt_avg.diff(-1)满足您的要求:“即当 Batt (avg) 从上一行增加时”。相反,对于给定的行,这显示了下一行中的值如何变化(乘以 -1)。如果您需要对上一行进行负面更改,则可以改用-df.Batt_avg.diff().

df['Batt_avg_diff'] = df.Batt_avg.diff(-1)

分组数据并应用聚合函数

您可以将分组条件表示df.podId.diff().fillna(0.0) != 0为 podId 和“电池更换之间,即两个负 Vdiff 值之间”df.Batt_avg_diff.fillna(0.0) < 0的条件- 其中任何一个都将触发一个新组。在触发器上使用以创建组。然后,您可以使用对这些组采取行动并将结果扩展到原始数据框的维度。cumsum()groupby()transform()

df['group'] = ((df.podId.diff().fillna(0.0) != 0) | (df.Batt_avg_diff.fillna(0.0) < 0)).cumsum()
df['Batt_avg_diff_sum'] = df.Batt_avg_diff.groupby(df.group).transform('sum')
df['Temp_avg_mean'] = df.Temp_avg.groupby(df.group).transform('mean')

日期时间计算

对于最后一步,您需要首先将字符串转换为日期时间以允许日期操作。然后您可以使用 groupby 操作来获取每个组中的最大值和最小值,并获取增量。

df.Time = pd.to_datetime(df.Time)
df['Time_days'] = df.Time.groupby(df.group).transform('max') - df.Time.groupby(df.group).transform('min')

注意:如果您不需要或不想要原始数据框中的聚合数据,只需直接应用函数(无需转换):

df_group = pd.DataFrame()
df_group['Batt_avg_diff_sum'] = df.Batt_avg_diff.groupby(df.group).sum()
df_group['Temp_avg_mean'] = df.Temp_avg.groupby(df.group).mean()
df_group['Time_days'] = df.Time.groupby(df.group).max() - df.Time.groupby(df.group).min()

推荐阅读