pandas dataframe:如何计算二进制列中 1 行的数量?
pandas dataframe: how to count the number of 1 rows in a binary column?
我有以下 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 的二进制列。有 "clusters" 个连续的,总是至少两个成对出现。
我的目标是创建一个列,其中 "counts" 每组的行数:
>>> 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]
...某事
我只是不确定如何考虑每个个体 "cluster",以及如何用 "row count" 标记每个独特的集群。
如何做到这一点?
- 因为
first_column
是二进制的,我可以用astype(bool)
得到True
/False
- 如果我采用相反的方法
cumsum
,我可以方便地将 True
s 或 1
s 集中在一起
- 然后我
groupby
和 count
与 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
这是 NumPy cumsum
and bincount
-
的一种方法
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
这是另一种使用 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
我有以下 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 的二进制列。有 "clusters" 个连续的,总是至少两个成对出现。
我的目标是创建一个列,其中 "counts" 每组的行数:
>>> 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]
...某事
我只是不确定如何考虑每个个体 "cluster",以及如何用 "row count" 标记每个独特的集群。
如何做到这一点?
- 因为
first_column
是二进制的,我可以用astype(bool)
得到True
/False
- 如果我采用相反的方法
cumsum
,我可以方便地将True
s 或1
s 集中在一起
- 然后我
groupby
和count
与transform
transform
在原始索引 中广播 - 我首先使用
where
将所有0
组合在一起。 - 我再次使用
where
将它们的计数设置为0
- 我使用
assign
生成带有新列的df
的副本。这是因为我不想破坏我们已有的df
。如果您想直接写入df
使用df['counts'] = c
count
聚合
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
这是 NumPy cumsum
and bincount
-
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
这是另一种使用 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