gpt4 book ai didi

python - Pandas 条件滚动计数

转载 作者:行者123 更新时间:2023-12-04 12:27:49 26 4
gpt4 key购买 nike

我有一个来自 Pandas: conditional rolling count 的问题.我想在数据框中创建一个新列,以反射(reflect)满足多个条件的行的累积计数。
使用以下示例和来自 stackoverflow 25119524 的代码

import pandas as pd


l1 =["1", "1", "1", "2", "2", "2", "2", "2"]
l2 =[1, 2, 2, 2, 2, 2, 2, 3]
l3 =[45, 25, 28, 70, 95, 98, 120, 80]
cowmast = pd.DataFrame(list(zip(l1, l2, l3)))

cowmast.columns =['Cow', 'Lact', 'DIM']

def rolling_count(val):
if val == rolling_count.previous:
rolling_count.count +=1
else:
rolling_count.previous = val
rolling_count.count = 1
return rolling_count.count
rolling_count.count = 0 #static variable
rolling_count.previous = None #static variable

cowmast['xmast'] = cowmast['Cow'].apply(rolling_count) #new column in dataframe

cowmast

输出是每头奶牛的 xmast(乳腺炎次数)
  Cow Lact DIM xmast0   1   1   45  11   1   2   25  22   1   2   28  33   2   2   70  14   2   2   95  25   2   2   98  36   2   2   120 47   2   3   80  5

What I would like to do is restart the count for each cow (cow) lactation (Lact) and only increment the count when the number of days (DIM) between rows is more than 7.

To incorporate more than one condition to reset the count for each cows lactation (Lact) I used the following code.


def count_consecutive_items_n_cols(df, col_name_list, output_col):
cum_sum_list = [
(df[col_name] != df[col_name].shift(1)).cumsum().tolist() for col_name in col_name_list
]
df[output_col] = df.groupby(
["_".join(map(str, x)) for x in zip(*cum_sum_list)]
).cumcount() + 1
return df

count_consecutive_items_n_cols(cowmast, ['Cow', 'Lact'], ['Lxmast'])

这会产生以下输出

Cow Lact DIM xmast Lxmast
0 1 1 45 1 1
1 1 2 25 2 1
2 1 2 28 3 2
3 2 2 70 1 1
4 2 2 95 2 2
5 2 2 98 3 3
6 2 2 120 4 4
7 2 3 80 5 1

我希望了解如何在累积计数中添加另一个条件,该条件考虑了乳腺炎事件之间的时间(同一 Lact 内奶牛的行之间的 DIM 差异)。如果同一头奶牛和泌乳牛的行之间的 DIM 差异小于 7,则计数不应增加。
我正在寻找的输出在下表中称为“已调整”。

Cow Lact DIM xmast Lxmast 已调整
0 1 1 45 1 1 1
1 1 2 25 2 1 1
2 1 2 28 3 2 1
3 2 2 70 1 1 1
4 2 2 95 2 2 2
5 2 2 98 3 3 2
6 2 2 120 4 4 3
7 2 3 80 5 1 1

在上面的示例中,牛 1 乳 2 当昏暗从 25 变为 28 时,计数不会增加,因为两个事件之间的差异小于 7 天。当从 95 到 98 时,母牛 2 乳 2 相同。对于较大的增量 70 到 95 和 98 到 120,计数增加。
感谢您的帮助
约翰

最佳答案

其实,你的密码设置xmastLxmast如果您使用了 referenced question 中获得最高票数的解决方案,则可以大大简化。 .
重命名您的数据框 cowmastdf ,您可以设置xmast如下:

df['xmast'] = df.groupby((df['Cow'] != df['Cow'].shift(1)).cumsum()).cumcount()+1
同理,设置 Lxmast , 您可以使用:
df['Lxmast'] = (df.groupby([(df['Cow'] != df['Cow'].shift(1)).cumsum(), 
(df['Lact'] != df['Lact'].shift()).cumsum()])
.cumcount()+1
)
数据输入
l1 =["1", "1", "1", "2", "2", "2", "2", "2"]
l2 =[1, 2, 2, 2, 2, 2, 2, 3]
l3 =[45, 25, 28, 70, 95, 98, 120, 80]
cowmast = pd.DataFrame(list(zip(l1, l2, l3)))

cowmast.columns =['Cow', 'Lact', 'DIM']

df = cowmast
输出
print(df)

Cow Lact DIM xmast Lxmast
0 1 1 45 1 1
1 1 2 25 2 1
2 1 2 28 3 2
3 2 2 70 1 1
4 2 2 95 2 2
5 2 2 98 3 3
6 2 2 120 4 4
7 2 3 80 5 1
现在,继续执行 中突出显示的需求的最后一部分。粗体 以下:

What I would like to do is restart the count for each cow (cow)lactation (Lact) and only increment the count when the number of days(DIM) between rows is more than 7.


我们可以这样做:
为了使代码更具可读性,让我们为迄今为止的代码定义 2 个分组序列:
m_Cow = (df['Cow'] != df['Cow'].shift()).cumsum()
m_Lact = (df['Lact'] != df['Lact'].shift()).cumsum()
然后,我们可以重写代码来设置 Lxmast以更易读的格式,如下:
df['Lxmast'] = df.groupby([m_Cow, m_Lact]).cumcount()+1
现在,转向这里的主要作品。假设我们创建了另一个新列 Adjusted为了它:
df['Adjusted'] = (df.groupby([m_Cow, m_Lact])
['DIM'].diff().abs().gt(7)
.groupby([m_Cow, m_Lact])
.cumsum()+1
)
结果:
print(df)

Cow Lact DIM xmast Lxmast Adjusted
0 1 1 45 1 1 1
1 1 2 25 2 1 1
2 1 2 28 3 2 1
3 2 2 70 1 1 1
4 2 2 95 2 2 2
5 2 2 98 3 3 2
6 2 2 120 4 4 3
7 2 3 80 5 1 1
在这里,在 df.groupby([m_Cow, m_Lact]) 之后,我们取列 DIM并通过 .diff() 检查每一行与前一行的差异并取绝对值 .abs() ,然后通过 .gt(7) 检查它是否 > 7在代码片段中 ['DIM'].diff().abs().gt(7) .然后我们再次按相同的分组进行分组 .groupby([m_Cow, m_Lact])因为这第三个条件在前两个条件的分组内。我们使用的最后一步 .cumsum() 在第三个条件上,所以只有当第三个条件为真时,我们才增加计数。
以防万一您只想在 DIM 时增加计数是 增加 > 7 仅(例如 70 到 78)并排除大小写 减少 > 7 (不是从 78 到 70),您可以删除 .abs()在上面的代码中的一部分:
df['Adjusted'] = (df.groupby([m_Cow, m_Lact])
['DIM'].diff().gt(7)
.groupby([m_Cow, m_Lact])
.cumsum()+1
)
编辑(可能的简化取决于您的数据序列)
由于您的示例数据具有主要分组键 CowLact有点已经在排序的顺序,有机会进一步简化代码。
不同于 referenced question的样本数据, 在哪里:
   col count
0 B 1
1 B 2
2 A 1 # Value does not match previous row => reset counter to 1
3 A 2
4 A 3
5 B 1 # Value does not match previous row => reset counter to 1
在这里,最后 B最后一行与其他分隔 B 's 并且它需要将计数重置为 1 而不是从最后一个 count 继续前 2 个 B (变成3)。因此,分组需要将当前行与前一行进行比较以获得正确的分组。否则,当我们使用 .groupby() 时以及 B 的值在处理过程中组合在一起, count最后一个条目的值可能无法正确重置为 1。
如果您的数据为主要分组键 CowLact在数据构建过程中已经自然排序,或者已经按指令排序,例如:
df = df.sort_values(['Cow', 'Lact'])
然后,我们可以简化我们的代码,如下所示:
(当数据已经按 [ Cow , Lact ] 排序时):
df['xmast'] = df.groupby('Cow').cumcount()+1
df['Lxmast'] = df.groupby(['Cow', 'Lact']).cumcount()+1

df['Adjusted'] = (df.groupby(['Cow', 'Lact'])
['DIM'].diff().abs().gt(7)
.groupby([df['Cow'], df['Lact']])
.cumsum()+1
)
3 列中的相同结果和输出值 xmast , LxmastAdjusted

关于python - Pandas 条件滚动计数,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/69241492/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com