Python 在特定条件下聚合Dataframe中的行值
我有一个Python 在特定条件下聚合Dataframe中的行值,python,pandas,dataframe,Python,Pandas,Dataframe,我有一个dataframe,它有两列。我想构建所有连续行的总和,其中列0的值为-1 我的dataframe看起来像这样: 0 2 1 3 -1 4 -1 7 0 2 -1 0 -1 1 -1 3 5 0 所需的输出应为: 0 2 1 3 -1 11 0 2 -1 4 5 0 第二列中的值都等于或大于零。如果有帮助,第一列上的值等于或大于-1。我的方法是一个循环,在循环中我创建第二个数据帧,然后将不等于-1的每个值推回
dataframe
,它有两列。我想构建所有连续行的总和,其中列0
的值为-1
我的dataframe
看起来像这样:
0 2
1 3
-1 4
-1 7
0 2
-1 0
-1 1
-1 3
5 0
所需的输出应为:
0 2
1 3
-1 11
0 2
-1 4
5 0
第二列中的值都等于或大于零。如果有帮助,第一列上的值等于或大于-1
。我的方法是一个循环,在循环中我创建第二个数据帧
,然后将不等于-1
的每个值推回并累积,当我发现一个-1
时,但我想,这种方法不会有效。
伪代码:
sum = 0
found = False
for row in dataframe:
if row[0] != -1:
if found:
new_df.append([-1, sum])
sum = 0
found = False
new_df.append(row)
elif row[0] == -1:
found = True
sum += row[1]
是否有内置python或pandas函数可用于实现我的目标?在我看来,如果助手组的值与
-1
之外的值相同,则必须100%确定创建系列,因此在索引中添加0.5
,以区分:
df = df.reset_index(drop=True)
m = df['a'] == -1
s = m.ne(m.shift()).cumsum()[m].reindex(df.index).fillna(df.index.to_series().add(.5))
df = df.groupby(s).agg({'a':'first', 'b':'sum'}).reset_index(drop=True)
print (df)
a b
0 0 2
1 1 3
2 -1 11
3 -1 4
4 0 2
5 5 0
说明:
df = pd.DataFrame({'a': [0, 1, -1, -1, 0, -1, -1, -1, 5],
'b': [2, 3, 4, 7, 2, 0, 1, 3, 0]})
print (df)
a b
0 0 2
1 1 3
2 -1 4
3 -1 7
4 0 2
5 -1 0
6 -1 1
7 -1 3
8 5 0
如有必要,首先创建默认索引,因为在解决方案中使用唯一的索引值:
df = df.reset_index(drop=True)
然后为-1
和其他值创建连续组:
m = df['a'] == -1
print (df.assign(groups = m.ne(m.shift()).cumsum()))
a b groups
0 0 2 1
1 1 3 1
2 -1 4 2
3 -1 7 2
4 0 2 3
5 -1 0 4
6 -1 1 4
7 -1 3 4
8 5 0 5
然后仅过滤-1
值(通过掩码b
),另一个不匹配的值通过以下方式转换为NaN
s:
然后用0.5
的索引值替换缺失的值-切勿在-1
组和替换的NaN
s组之间合并:
m = df['a'] == -1
print (df.assign(groups = m.ne(m.shift()).cumsum(),
filtered = m.ne(m.shift()).cumsum()[m].reindex(df.index),
idx = df.index.to_series().add(.5),
groups1 = m.ne(m.shift()).cumsum()[m].reindex(df.index).fillna(df.index.to_series().add(.5))))
a b groups filtered idx groups1
0 0 2 1 NaN 0.5 0.5
1 1 3 1 NaN 1.5 1.5
2 -1 4 2 2.0 2.5 2.0
3 -1 7 2 2.0 3.5 2.0
4 0 2 3 NaN 4.5 4.5
5 -1 0 4 4.0 5.5 4.0
6 -1 1 4 4.0 6.5 4.0
7 -1 3 4 4.0 7.5 4.0
8 5 0 5 NaN 8.5 8.5
然后将helperSeries
传递给groupby
,并将第二列的sum
和第一列的first
进行聚合,最后一列通过drop=True删除索引:
df = df.groupby(s).agg({'a':'first', 'b':'sum'}).reset_index(drop=True)
print (df)
a b
0 0 2
1 1 3
2 -1 11
3 -1 4
4 0 2
5 5 0
另一种更简单、性能更好的解决方案:
df = df.reset_index(drop=True)
m = df['a'] == -1
s = df.reset_index()
.groupby(m.ne(m.shift()).cumsum()[m])
.agg({'index':'first', 'b':'sum'})
.set_index('index')
.assign(a = -1)
df = df[~m].append(s, sort=True).sort_index()
print (df)
a b
0 0 2
1 1 3
2 -1 11
4 0 2
5 -1 4
8 5 0
说明:
df = pd.DataFrame({'a': [0, 1, -1, -1, 0, -1, -1, -1, 5],
'b': [2, 3, 4, 7, 2, 0, 1, 3, 0]})
print (df)
a b
0 0 2
1 1 3
2 -1 4
3 -1 7
4 0 2
5 -1 0
6 -1 1
7 -1 3
8 5 0
首先是必要的默认索引:
df = df.reset_index(drop=True)
然后将-1
列与布尔掩码进行比较:
m = df['a'] == -1
通过reset_index
将索引转换为列,无drop
参数:
print (df.reset_index())
index a b
0 0 0 2
1 1 1 3
2 2 -1 4
3 3 -1 7
4 4 0 2
5 5 -1 0
6 6 -1 1
7 7 -1 3
8 8 5 0
使用shift
和cumsum
创建连续组,并按掩码为-1
组进行筛选:
print (m.ne(m.shift()).cumsum()[m])
2 2
3 2
5 4
6 4
7 4
Name: a, dtype: int32
按索引列聚合first
,按b
列聚合sum
print (df.reset_index()
.groupby(m.ne(m.shift()).cumsum()[m])
.agg({'index':'first', 'b':'sum'}))
index b
a
2.0 2 11
4.0 5 4
通过以下方式将索引
列转换为索引
:
通过以下方式添加具有常量-1
的列:
最后一次过滤出-1
行,使用反向掩码按~
:
print (df[~m])
a b
0 0 2
1 1 3
4 0 2
8 5 0
然后通过以下方式将新数据添加到原始数据:
最后,对于相同的订购:
print (df[~m].append(s, sort=True).sort_index())
a b
0 0 2
1 1 3
2 -1 11
4 0 2
5 -1 4
8 5 0
你能详细地告诉我每一行发生了什么吗?我是python新手,但我想确定,我正确地、以最佳方式使用了pythonpossible@RoQuOTriX-添加解释,使用-1
解决第一个值的任何值。
print (df[~m])
a b
0 0 2
1 1 3
4 0 2
8 5 0
print (df[~m].append(s, sort=True))
a b
0 0 2
1 1 3
4 0 2
8 5 0
2 -1 11
5 -1 4
print (df[~m].append(s, sort=True).sort_index())
a b
0 0 2
1 1 3
2 -1 11
4 0 2
5 -1 4
8 5 0