我有一个从Pandas: conditional rolling count开始的问题。我想在dataframe中创建一个新列,该列反映满足多个条件的行的累积计数
使用以下示例和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 xmast 0 1 1 45 1 1 1 2 25 2 2 1 2 28 3 3 2 2 70 1 4 2 2 95 2 5 2 2 98 3 6 2 2 120 4 7 2 3 80 5
我想做的是重新开始计算每头奶牛(奶牛)的泌乳量(Lact),并且仅当两行之间的天数(DIM)超过7天时才增加计数
为了合并多个条件来重置每头奶牛的泌乳(Lact)计数,我使用了以下代码
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
我希望了解如何在累积计数中添加另一个条件,考虑乳腺炎事件之间的时间(同一乳汁中奶牛行间的DIM差异)。如果同一头牛和哺乳期的行间DIM差异小于7,则计数不应增加
我正在寻找的输出在下表中称为“调整”
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
在上述示例中,对于奶牛1乳2,当dim从25变为28时,计数不会增加,因为两个事件之间的差值小于7天。当is从95变为98时,奶牛2乳2也是如此。对于较大的增量70至95和98至120,计数增加
谢谢你的帮助
约翰
实际上,如果使用了referenced question中具有最高投票权的解决方案,那么设置
xmast
和Lxmast
的代码可以大大简化将数据帧
cowmast
重命名为df
,可以按如下方式设置xmast
:类似地,要设置
Lxmast
,可以使用:数据输入
输出
现在,继续您的需求的最后一部分,在下面的粗体中突出显示:
我们可以这样做:
为了使代码更具可读性,让我们为迄今为止的代码定义2个分组序列:
然后,我们可以重写代码,以更可读的格式设置
Lxmast
,如下所示:现在,转到这里的主要工作。假设我们为它创建另一个新列
Adjusted
:结果:
在这里,在} 检查每一行与前一行的差异,通过^{} 获取绝对值,然后检查它是否为>;在代码片段} 执行7。然后,我们再次按相同的分组} ,因此只有当第三个条件为真时,我们才增加计数
df.groupby([m_Cow, m_Lact])
之后,我们获取列DIM
,并通过^{['DIM'].diff().abs().gt(7)
中,由^{.groupby([m_Cow, m_Lact])
,因为第三个条件在前两个条件的分组范围内。最后一步,我们在第三个条件上使用^{以防万一,仅当
DIM
被>;7仅限(如70至78),不包括减少了>;7(不是从78到70),您可以删除上述代码中的.abs()
部分:编辑(可能的简化取决于您的数据序列)
由于示例数据中的主要分组键
Cow
和Lact
已经在排序顺序中,因此有机会进一步简化代码与来自referenced question的示例数据不同,其中:
这里,最后一行中的最后一个
B
与其他B
分开,它要求将计数重置为1,而不是从前一个B
中2个的最后一个count
继续(变为3)。因此,分组需要将当前行与前一行进行比较,以获得正确的分组。否则,当我们使用.groupby()
并且B
的值在处理过程中分组在一起时,最后一个条目的count
值可能无法正确重置为1如果主分组键
Cow
和Lact
的数据在数据构造期间已自然排序,或已按指令排序,例如:然后,我们可以简化代码,如下所示:
(当数据已按[
Cow
,Lact
排序时):3列
xmast
、Lxmast
和Adjusted
中的结果和输出值相同相关问题 更多 >
编程相关推荐