Groupby 熊猫但对多列执行计算

时间:2021-04-01 18:50:51

标签: python pandas

我有一个如下所示的数据框:

<头>
名称 日期 col1 col2
A 2021-03-01 0 1
A 2021-03-02 0 0
A 2021-03-03 3 1
A 2021-03-04 1 0
A 2021-03-05 3 1
A 2021-03-06 1 0
B 2021-03-01 1 0
B 2021-03-02 2 0
B 2021-03-03 3 1
B 2021-03-04 0 1
B 2021-03-05 0 0
B 2021-03-06 0 0

我想按名称分组并找到其他非日期列的非零条目(基本上不包括任何前导零或尾随零)所跨越的天数,以获得类似的结果:

<头>
名称 col1 col2
A 4 5
B 3 2

如何在不使用 for 循环的情况下执行此操作?

3 个答案:

答案 0 :(得分:4)

我认为,np.trim_zeros 正是您要找的:

>>> import numpy as np; import pandas as pd
>>> df = pd.DataFrame.from_dict({'name': ['A']*6 + ['B']*6, 'col1': [0, 0, 3, 1, 3, 1, 1, 2, 3, 0, 0, 0], 'col2': [1, 0, 1, 0, 1, 0, 0, 0, 1, 1, 0, 0]})

>>> df
   name  col1  col2
0     A     0     1
1     A     0     0
2     A     3     1
3     A     1     0
4     A     3     1
5     A     1     0
6     B     1     0
7     B     2     0
8     B     3     1
9     B     0     1
10    B     0     0
11    B     0     0

>>> df.groupby('name').aggregate(lambda x: len(np.trim_zeros(x))).reset_index()
  name  col1  col2
0    A     4     5
1    B     3     2

答案 1 :(得分:1)

另一种解决方案:

def fn(x):
    i = x[(x != 0)].index
    return i[-1] - i[0] + 1 if len(i) > 0 else 0


print(df.groupby("name").agg({"col1": fn, "col2": fn}))

打印:

      col1  col2
name            
A        4     5
B        3     2

答案 2 :(得分:0)

这里有一种方法可以更好地为许多组扩展[它避免了 apply(lambda x:) 以支持多个 groubpy 内置操作。]

检查值 !=0 然后在组内在两个方向上取一个 cummax 用 True 标记跨度。然后 groupby + sum 得到大小。

cols = ['col1', 'col2']
df1 = df[cols].ne(0)

df1 = df1.groupby(df['name']).cummax() & df1[::-1].groupby(df['name']).cummax()
df1 = df1.groupby(df['name']).sum()

print(df1)

      col1  col2
name            
A        4     5
B        3     2