如何根据其他列的函数 select/add 一列到 pandas 数据框?

how to select/add a column to pandas dataframe based on a function of other columns?

我有一个数据框,我想 select 符合某些条件的行。该条件是其他列值和一些附加值的函数。

这是一个玩具示例:

>>df = pd.DataFrame({'A': [1,2,3,4,5,6,7,8,9],
                   'B': [randint(1,9) for x in xrange(9)],
                   'C': [4,10,3,5,4,5,3,7,1]})
>>

      A  B   C
   0  1  6   4
   1  2  8  10
   2  3  8   3
   3  4  4   5
   4  5  2   4
   5  6  1   5
   6  7  1   3
   7  8  2   7
   8  9  8   1

并且我想要 select 某些函数 returns 为真的所有行,例如f(a,c,L) returns 真当且仅当乘法 AxC 在指定的列表 L 中,比如 L=[4,20,30](尽管该函数可能不那么简单)。即我要得到:

>>
      A  B   C
   0  1  6   4
   1  2  8  10
   3  4  4   5
   4  5  2   4
   5  6  1   5

同样,我想添加第四个二进制列 'matched',它是 True is AxC in L:

      A  B   C  matched
   0  1  2   4    True
   1  2  5  10    True
   2  3  6   3   False
   3  4  3   5    True
   4  5  2   4    True
   5  6  6   5    True
   6  7  4   3   False
   7  8  5   7   False
   8  9  2   1   False

(添加此列后,您可以轻松地 select 所有具有 True 的行,但我怀疑一旦可以添加,您也可以 select)。

有没有一种高效而优雅的方法可以在不显式迭代所有索引的情况下做到这一点? 谢谢!

这将return一个布尔索引

L=[4,20,30]
df.apply(lambda x : True if (x['A'] * x['C']) in L else False, axis=1)

0     True
1     True
2    False
3     True
4     True
5     True
6    False
7    False
8    False

然后你可以做什么

rowindex = df.apply(lambda x : True if (x['A'] * x['C']) in L else False, axis=1)
df.loc[rowindex,'match'] = True
df.loc[~rowindex,'match'] = False
df

    A   B   C   match
0   1   7   4   True
1   2   3   10  True
2   3   9   3   False
3   4   5   5   True
4   5   9   4   True
5   6   2   5   True
6   7   2   3   False
7   8   7   7   False
8   9   6   1   False

使用isin的向量化解决方案:

In [5]:

L=[4,20,30]
df['Match'] = (df['A']*df['C']).isin(L)
df
Out[5]:
   A  B   C  Match
0  1  6   4   True
1  2  1  10   True
2  3  8   3  False
3  4  4   5   True
4  5  2   4   True
5  6  4   5   True
6  7  4   3  False
7  8  7   7  False
8  9  4   1  False

时间安排:

In [9]:

%%timeit
L=[4,20,30]
rowindex = df.apply(lambda x : True if (x['A'] * x['C']) in L else False, axis=1)
df.loc[rowindex,'match'] = True
df.loc[~rowindex,'match'] = False
100 loops, best of 3: 3.13 ms per loop
In [11]:

%%timeit 
L=[4,20,30]
df['Match'] = (df['A']*df['C']).isin(L)

1000 loops, best of 3: 678 µs per loop