基于其他列进行多重查找,向Pandas DataFrame添加一列

3

我想给以下的DataFrame添加一列(col5),其中col5中的值需要满足另一列在同一行中的特定条件,来自col4。例如,在col5的第1行,我希望从col4中选择一个值,使得col1和col2的值与第1行相同,但col3的值不等于第1行。在Excel中,可以使用sumifs函数来实现如下所示的操作。感谢任何帮助。 Image shown in the link below 根据Paul的答案,我更新了我的问题。

df=pd.DataFrame({"col1":[1,1,1,1,2,2,2,2], "col2":['a','a','b', 'b','c', 'c', 'd', 'd'], "col3":['p','q','p', 'q', 'p','q','p', 'q'], 'col4':[100,200,300,400,500,600,700,800]})

我想要实现的是像下面这样添加一个col5,它会检查其他列中的条件,其中col1col2应该相同,但col3不应匹配。假设col3只有两个不同的值,所以说col3不匹配意味着col3应该有另一个值。
df2 = df

df['col5'] = df[(df.col1 == df2.col1) & (df.col2 == df2.col2) & (df.col3 != df2.col3)].col4

df

>>>

  col1 col2 col3 col4   col5
0   1   a    p   100    NaN
1   1   a    q   200    NaN
2   1   b    p   300    NaN
3   1   b    q   400    NaN
4   2   c    p   500    NaN
5   2   c    q   600    NaN
6   2   d    p   700    NaN
7   2   d    q   800    NaN

运行此代码时,如上所示,我在col5中得到所有的NaN。
我想要得到的结果如下所示。这里的排列方式似乎很简单,就像从下一行或上一行获取一样,但在扩展数据中,它可能位于任何行。
>>>

  col1 col2 col3 col4   col5
0   1   a    p   100    200
1   1   a    q   200    100
2   1   b    p   300    400
3   1   b    q   400    300
4   2   c    p   500    600
5   2   c    q   600    500
6   2   d    p   700    800
7   2   d    q   800    700

请提供样本数据以及期望的输出数据框,以便进行可重复的测试。 - sammywemmy
我分享了一个可能的答案,不确定它是否是你要寻找的答案。请像@sammywemmy建议的那样,在你的问题中添加一个期望的输出数据框。 - Paul
抱歉我没有以可重现的格式附上数据。我的错。非常感谢保罗为此所做的努力。 - sri
2个回答

1
你的问题对我来说不是很清楚,但我理解的是: 检查col1和col2是否与下一行相同,但col3不同。
如果是这样:获取下一行的col4值作为col5。
df=pd.DataFrame({"col1":[1,1,1,1,2,2,2,2], "col2":['a','a','b', 'b','c', 'c', 'd', 'd'], "col3":['p','q','p', 'q', 'p','q','p', 'q'], 'col4':[100,200,300,400,500,600,700,800]})

df2 = df.shift(-1)
df['col5'] = df2[(df.col1 == df2.col1) & (df.col2 == df2.col2) & (df.col3 != df2.col3)].col4

df

        col1    col2    col3    col4    col5
0       1       a       p       100     200.0
1       1       a       q       200     NaN
2       1       b       p       300     400.0
3       1       b       q       400     NaN
4       2       c       p       500     600.0
5       2       c       q       600     NaN
6       2       d       p       700     800.0
7       2       d       q       800     NaN

更新

如果您还想查找其他值,请使用apply

df['col5'] = df.apply(
    lambda x: df[
        (df.col1 == x.col1) & 
        (df.col2 == x.col2) & 
        (df.col3 != x.col3)
        ].reset_index()['col4'],
    axis=1)

这是一种更好的迭代行的方法。

如果我的回答有用/有帮助,请不要犹豫给它点赞。 - Paul
非常感谢Paul将数据整理成正确的形式。我发现我的问题并不是很清楚,但是你提出的解决方案给了我可能缺失的想法。我不知道如何像df['col1'] = df['col1']或df['col3']!= df['col3']那样做些什么。但从你的答案中我看到了一些启示,可以尝试一些东西,并更好地解释问题。我已根据此更新了我的问题。 - sri
@sri,我更新了我的答案,现在符合你想要的输出。 - Paul
谢谢,这比我的迭代方法高效多了。 - sri

1

我想我找到了如何做到这一点。我目前正在迭代每行数据框以完成任务。

for i in range(len(df)):
  df.loc[i,'col5'] = df[(df.col1 == df.loc[i,'col1']) & (df.col2 == 
  df.loc[i,'col2']) & (df.col3 != df.loc[i,'col3'])].col4.sum()

df
>>>
 col1 col2 col3 col4 col5
0   1   a   p   100  200.0
1   1   a   q   200  100.0
2   1   b   p   300  400.0
3   1   b   q   400  300.0
4   2   c   p   500  600.0
5   2   c   q   600  500.0
6   2   d   p   700  800.0
7   2   d   q   800  700.0

我很乐意知道是否有更好、更高效的方法来完成这个任务,而不需要迭代。谢谢!


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接