Python 熊猫匹配多个列,并将匹配值作为单个新列获取

Python 熊猫匹配多个列,并将匹配值作为单个新列获取,python,pandas,dataframe,Python,Pandas,Dataframe,我有一个大约有5列的数据框。我希望匹配的值可以出现在最后3列中 Key | col1 | col2 | col3 | col4 ---------------------------------------- 1 abc 21 22 23 2 cde 22 21 20 3 fgh 20 22 23 4 lmn

我有一个大约有5列的数据框。我希望匹配的值可以出现在最后3列中

Key   |  col1   |  col2  |  col3 |  col4
----------------------------------------
1        abc       21        22      23
2        cde       22        21      20
3        fgh       20        22      23
4        lmn       20        22      21
我对最后三列中的任何一列的值
21
进行过滤,如下所示:

df1=df[(df['col2']='21')|(df['col3']='21')|(df['col4']='21')。

这让我

Key   |  col1   |  col2  |  col3 |  col4
----------------------------------------
1        abc       21        22      23
2        cde       22        21      20
4        lmn       20        22      21
使用这个新的df1,我想得到这个

Key   |  col1   |  newCol
-------------------------
1        abc       21      
2        cde       21      
4        lmn       21      
基本上任何匹配的列都可以作为新列的值。我如何使用熊猫来实现这一点?我感谢你的帮助。所以我想可能我应该同时过滤并将其映射到新列,但我不知道如何使用

In [722]: df.loc[df[['col2', 'col3', 'col4']].eq(21).any(1), 
                 ['Key', 'col1']].assign(newcol=21)
Out[722]:
   Key col1  newcol
0    1  abc      21
1    2  cde      21
3    4  lmn      21

细节

在必要的
['col2'、'col3'、'col4']列上进行等式检查
eq

In [724]: df[['col2', 'col3', 'col4']].eq(21)
Out[724]:
    col2   col3   col4
0   True  False  False
1  False   True  False
2  False  False  False
3  False  False   True
any
将返回行中任何元素是否为True

In [725]: df[['col2', 'col3', 'col4']].eq(21).any(1)
Out[725]:
0     True
1     True
2    False
3     True
dtype: bool
使用
.loc
对匹配的行和必要的
['Key','col1']
列进行子集设置

In [726]: df.loc[df[['col2', 'col3', 'col4']].eq(21).any(1), ['Key', 'col1']]
Out[726]:
   Key col1
0    1  abc
1    2  cde
3    4  lmn
并且,
.assign(newcol=21)
创建一个
newcol
列,设置为
21
,这里是一种方法

import pandas as pd, numpy as np

df = pd.DataFrame([[1, 'abc', 21, 22, 23],
                   [2, 'cde', 22, 21, 20],
                   [3, 'fgh', 20, 22, 23],
                   [4, 'lmn', 20, 22, 21]],
                  columns=['Key', 'col1', 'col2', 'col3', 'col4'])

df2 = df[np.logical_or.reduce([df[col] == 21 for col in ['col2', 'col3', 'col4']])]\
        .assign(newCol=21)\
        .drop(['col2', 'col3', 'col4'], 1)

#    Key col1  newCol
# 0    1  abc      21
# 1    2  cde      21
# 3    4  lmn      21
解释

  • 将整数存储为整数而不是字符串
  • np.logical_或.reduce
    在列表中应用您的
    条件
  • assign
    使用筛选值创建一个新列
  • drop
    删除不需要的列,
    axis=1
    指列

正如jpp所指出的,这里有两种可能性:21和22在所有3列中都很常见。假设您不知道真正要查找的是哪一列,您可以使用
set()
来隔离每列的唯一值,然后使用
set.intersection()
来查找共性:

df = pd.DataFrame([{'col1':'a', 'col2':21, 'col3':22, 'col4':23},
                   {'col1':'b', 'col2':22, 'col3':21, 'col4':20},
                   {'col1':'c', 'col2':20, 'col3':22, 'col4':21},
                   {'col1':'d', 'col2':21, 'col3':21, 'col4':22}])

s1 = set(df['col2'].values)
s2 = set(df['col3'].values)
s3 = set(df['col4'].values)

df['new_col'] = str(s1.intersection(s2, s3))
df

col1    col2    col3    col4    new_col
   a    21      22      23      {21, 22}
   b    22      21      20      {21, 22}
   c    20      22      21      {21, 22}
   d    21      21      22      {21, 22}

从第二个数据帧中,您如何知道过滤了哪个值?在本例中,它可能是21或22。如果您知道匹配的值,为什么不能创建新列作为此值?或者,您是否要求提取3个结果列中存在的公共值(不知道它是'21')?对,我不知道是哪一个。所以我想我应该同时过滤并映射到新的专栏,但我不知道怎么做?这两种方法都有效,但我只能接受一种。接受这个解释。我将从@Zero向上投票另一个答案。我非常感谢你的帮助。imho-这绝对是最好的答案-如果有更多的解释-那太好了:)