Pandas - 在两列中查找具有匹配值的行并在另一列中相乘
Posted
技术标签:
【中文标题】Pandas - 在两列中查找具有匹配值的行并在另一列中相乘【英文标题】:Pandas - find rows with matching values in two columns and multiply value in another column 【发布时间】:2019-01-19 08:31:47 【问题描述】:首先假设我们下面有一个数据框:
import pandas as pd
data = pd.DataFrame('id':['1','2','3','4','5','6','7','8'],
'A':['foo', 'bar', 'foo', 'bar','foo', 'bar', 'foo', 'foo'],
'C':['10','10','10','30','50','60','50','8'],
'D':['9','8','7','6','5','4','3','2'])
print(data)
A C D id
0 foo 10 9 1
1 bar 10 8 2
2 foo 10 7 3
3 bar 30 6 4
4 foo 50 5 5
5 bar 60 4 6
6 foo 50 3 7
7 foo 8 2 8
我想做的是找到匹配的行,然后做一些计算。
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']
的新数据框。
所以几行预期的结果是:
id A result
0 1 foo 63
1 3 foo 63
2 5 foo 15
3 7 foo 15
我试过了,但结果要么是错误的逻辑,要么是错误的代码/数据格式。 有人可以帮帮我吗?
【问题讨论】:
我的回答有用吗? 【参考方案1】:您可以使用自连接技术:
data[['id', 'C', 'D']] = data[['id', 'C', 'D']].apply(pd.to_numeric)
joint = pd.merge(data, data, on=('A', 'C'))
joint = joint.loc[join['id_x'] != join['id_y']]
joint['result'] = joint['D_x'] * joint['D_y']
result = joint[['id_x', 'A', 'result']]
result.columns = ['id', 'A', 'result']
结果:
id A result
1 1 foo 63
2 3 foo 63
7 5 foo 15
8 7 foo 15
【讨论】:
更好更快joint['result'] = joint['D_x'] * joint['D_y']
而不是joint['result'] = joint.apply(lambda x: x['D_x'] * x['D_y'], axis=1)
也可以这样做:joint = pd.merge(data, data, on=('A', 'C'))[lambda r: r.id_x != r.id_y]
但它可能更慢...
我得到 'function' 对象不可下标且无法运行
先生,当我尝试处理大型数据集时,您的回答会导致内存错误。你有什么解决办法吗? @Lev Zakharov【参考方案2】:
一种方法是按A + C分组,取产品并计数,过滤掉组中只有一个项目的那些,然后在A + C上内部合并回您的原始框架,例如:
df.merge(
df.groupby(['A', 'C']).D.agg(['prod', 'count'])
[lambda r: r['count'] > 1],
left_on=['A', 'C'],
right_index=True
)
给你:
A C D id prod count
0 foo 10 9 1 63 2
2 foo 10 7 3 63 2
4 foo 50 5 5 15 2
6 foo 50 3 7 15 2
然后根据需要删除/重命名列。
【讨论】:
我很困惑。 OP 是否要求过滤组中行数的特定行?我将问题编辑为few rows of the output would be
,在他解释他想要什么时,他没有说他没有添加只会返回计数为2的那些行的逻辑部分。
嗯好吧。我按照他的逻辑走。
您好,先生,我有一个与此相关的new question。你介意花点时间检查一下吗?谢谢!【参考方案3】:
import pandas as pd
data = pd.DataFrame('id':['1','2','3','4','5','6','7','8'],
'A':['foo', 'bar', 'foo', 'bar','foo', 'bar', 'foo', 'foo'],
'C':['10','10','10','30','50','60','50','8'],
'D':['9','8','7','6','5','4','3','2'])
先将相关列转换为数值
data[['C', 'D', 'id']] = data[['C', 'D', 'id']].apply(pd.to_numeric)
创建空的 DataFrame 以追加到
finalDataFrame = pd.DataFrame()
groupby
两列,然后在组内找到列D
的乘积并追加。
group = data.groupby(['A', 'C'])
for x, y in group:
product = (y[["D"]].product(axis=0).values[0])
for row in y.index:
y.at[row, 'D'] = product
finalDataFrame = finalDataFrame.append(y, ignore_index=True)
output = finalDataFrame[['id', 'A', 'D']]
output = output.rename(columns = 'D': 'result')
print(output)
给你
id A result
0 2 bar 8
1 4 bar 6
2 6 bar 4
3 8 foo 2
4 1 foo 63
5 3 foo 63
6 5 foo 15
7 7 foo 15
【讨论】:
以上是关于Pandas - 在两列中查找具有匹配值的行并在另一列中相乘的主要内容,如果未能解决你的问题,请参考以下文章
Pandas:在多列中查找具有匹配值的行的 Pythonic 方法(分层条件)
从数据框中删除重复项,基于两列 A,B,在另一列 C 中保持具有最大值的行