![](/img/trans.png)
[英]Pandas - find rows with matching values in two columns and multiply value in another column
[英]Pandas - find and iterate rows with matching values in multiple columns and multiply value in another column
这个问题比我之前的问题更进了一步:
我编辑了表格,这样可以减少混淆
首先假设我们有一个数据框如下:
data = pd.DataFrame({'id':['1','2','3','4','5','6','7','8','9','10'],
'A':['foo', 'bar', 'foo', 'bar','foo', 'bar', 'foo', 'foo','foo','bar'],
'C':['10','10','10','50','50','50','50','8','10','20'],
'D':['10','9','8','7','6','5','4','3','2','1']})
如下:
A C D id
0 foo 10 10 1
1 bar 10 9 2
2 foo 10 8 3
3 bar 50 7 4
4 foo 50 6 5
5 bar 50 5 6
6 foo 50 4 7
7 foo 8 3 8
8 foo 10 2 9
9 bar 20 1 10
我想做的是找到匹配行,然后进行一些计算。
for any two ids(idx, idy) in data.iterrows():
if idx.A == idy.A and idx.C = idy.C:
result = idx.D * idy.D
然后生成一个包含三列['id']
, ['A']
和['result']
的新数据帧。
@Jon Clements♦使用下面非常简洁的代码回答了我之前的问题:
df.merge(
df.groupby(['A', 'C']).D.agg(['prod', 'count'])
[lambda r: r['count'] > 1],
left_on=['A', 'C'],
right_index=True
)
新目标:
现在我想知道有没有一种方法在与row_b匹配时不再迭代row_a。 换句话说,我认为这两个匹配的行是一对。 一旦row_a和row_b成为一对,另一个循环将忽略row_a(而不是row_b,直到row_b与另一行匹配)。
以groupby().agg('prod', 'count')
函数为例,我希望生成的所有结果的'count'
为2(不仅仅是['count'] == 2
的过滤器)。 我认为这不会使用groupby()
所以我认为像for循环这样的机制可以解决这个问题吗? 或者有更好的方法吗?
所以现在的预期结果是(因为id1和id3已成为一对,因此它不会聚合到id9,而对于其余迭代,id3将不会与id1匹配。因此,对于下表,第一行的结果为80但不是160 ,第二行也不是):
id A result
0 1 foo 80
1 3 foo 16
2 4 bar 35
3 5 foo 24
我的英语不太好,所以我不确定我是否清楚地解释了我的问题。 如果你不清楚,问我什么。
谢谢你的帮助。
这是一个冗长的解决方案,远不及Jon Clements为您解决的第一个问题的原始解决方案。 但我提出了一个解决方案,而不需要for-loop。
# sort values by A,C,id
df = df.sort_values(['A','C','id'])
# find where A and C are equal when shifted down by 1
s=(df[['A','C']] == df[['A','C']].shift()).T.apply(lambda x: x.A and x.C)
# create a new series where we take the value of D of whe A and C are equal
# and multiply it with the next value - since it's sorted it should be next A,C match
new_d = (df.iloc[df[s].index].reset_index().D * df.iloc[df[s].index+1].reset_index().D)
new_d.index = df.iloc[df[s].index].index
new_d.name = 'results'
print(new_d)
Output >
0 80
3 35
4 24
2 16
Name: results, dtype: int64
考虑到上述情况,我们只需在df
创建一个新列并将其分配给new_d
:
# create a new column in df and assign it to new_d
df['results'] = new_d
df.dropna()[['id','A','results']].sort_values('id')
输出:
id A results
0 1 foo 80.0
2 3 foo 16.0
3 4 bar 35.0
4 5 foo 24.0
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.