pandas dataframe:如何计算二进制列中1行的数量?

时间:2017-04-25 16:26:07

标签: python pandas dataframe group-by pandas-groupby

我有以下pandas DataFrame:

import pandas as pd
import numpy as np

df = pd.DataFrame({"first_column": [0, 0, 0, 1, 1, 1, 0, 0, 1, 1, 0, 0, 0, 0, 1, 1, 1, 1, 1, 0, 0]})

>>> df
    first_column
0              0
1              0
2              0
3              1
4              1
5              1
6              0
7              0
8              1
9              1
10             0
11             0
12             0
13             0
14             1
15             1
16             1
17             1
18             1
19             0
20             0

first_column是0和1的二进制列。存在连续的“簇”,它们总是成对出现至少两个。

我的目标是创建一个“计算”每个组的行数的列:

>>> df
    first_column    counts
0              0        0
1              0        0
2              0        0
3              1        3
4              1        3
5              1        3
6              0        0
7              0        0
8              1        2
9              1        2
10             0        0
11             0        0
12             0        0
13             0        0
14             1        5
15             1        5
16             1        5
17             1        5
18             1        5
19             0        0
20             0        0

这听起来像是df.loc()的工作,例如df.loc[df.first_column == 1] ...东西

我只是不确定如何考虑每个“群集”的群集,以及如何使用“行数”标记每个唯一群集。

怎么会这样做?

3 个答案:

答案 0 :(得分:5)

  • 由于first_column是二进制文件,我可以使用astype(bool)获取True / False
  • 如果我采取与cumsum相反的方式,我可以方便地将True1 s
  • 混为一谈
  • 然后我groupbycount transform
  • transform在原始索引
  • 中广播count聚合
  • 我首先使用where将所有0组合在一起。
  • 我再次使用where将其计数设置为0
  • 我使用assign生成带有新列的df副本。这是因为我不想破坏我们已有的df。如果您想直接写入df使用df['counts'] = c
t = df.first_column.astype(bool)
c = df.groupby((~t).cumsum().where(t, -1)).transform('count').where(t, 0)
df.assign(counts=c)

    first_column  counts
0              0       0
1              0       0
2              0       0
3              1       3
4              1       3
5              1       3
6              0       0
7              0       0
8              1       2
9              1       2
10             0       0
11             0       0
12             0       0
13             0       0
14             1       5
15             1       5
16             1       5
17             1       5
18             1       5
19             0       0
20             0       0

答案 1 :(得分:5)

这是NumPy cumsumbincount的一种方法 -

def cumsum_bincount(a):  
    # Append 0 & look for a [0,1] pattern. Form a binned array based off 1s groups
    ids = a*(np.diff(np.r_[0,a])==1).cumsum()

    # Get the bincount, index into the count with ids and finally mask out 0s
    return a*np.bincount(ids)[ids]

示例运行 -

In [88]: df['counts'] = cumsum_bincount(df.first_column.values)

In [89]: df
Out[89]: 
    first_column  counts
0              0       0
1              0       0
2              0       0
3              1       3
4              1       3
5              1       3
6              0       0
7              0       0
8              1       2
9              1       2
10             0       0
11             0       0
12             0       0
13             0       0
14             1       5
15             1       5
16             1       5
17             1       5
18             1       5
19             0       0
20             0       0

将第一个6元素设置为1s,然后测试 -

In [101]: df.first_column.values[:5] = 1

In [102]: df['counts'] = cumsum_bincount(df.first_column.values)

In [103]: df
Out[103]: 
    first_column  counts
0              1       6
1              1       6
2              1       6
3              1       6
4              1       6
5              1       6
6              0       0
7              0       0
8              1       2
9              1       2
10             0       0
11             0       0
12             0       0
13             0       0
14             1       5
15             1       5
16             1       5
17             1       5
18             1       5
19             0       0
20             0       0

答案 2 :(得分:0)

这是另一种使用pandas groupby的方法,我认为它非常易读。 (可能的)优点是不依赖于列中仅存在1和0的假设。

主要的见解是创建连续值组,然后简单地计算它们的长度。我们还携带组中值的信息,因此我们可以过滤零。

# Relevant column -> grouper needs to be 1-Dimensional
col_vals = df['first_column']

# Group by sequence of consecutive values and value in the sequence.
grouped = df.groupby(((col_vals!=col_vals.shift(1)).cumsum(), col_vals))

# Get the length of consecutive values if they are different from zero, else zero
df['counts'] = grouped['first_column'].transform(lambda group: len(group))\
                                      .where(col_vals!=0, 0)

这就是组和键的样子:

for key, group in grouped:
    print key, group

(1, 0)    first_column
0             0
1             0
2             0
(2, 1)    first_column
3             1
4             1
5             1
(3, 0)    first_column
6             0
7             0
(4, 1)    first_column
8             1
9             1
(5, 0)     first_column
10             0
11             0
12             0
13             0
(6, 1)     first_column
14             1
15             1
16             1
17             1
18             1
(7, 0)     first_column
19             0
20             0