Pandas列的向量化“and”

5

有了这样的数据

import pandas as pd
tcd = pd.DataFrame({
 'a': {'p_1': 1, 'p_2': 1, 'p_3': 0, 'p_4': 0}, 
 'b': {'p_1': 0, 'p_2': 1, 'p_3': 1, 'p_4': 1}, 
 'c': {'p_1': 0, 'p_2': 0, 'p_3': 1, 'p_4': 0}})
tcd
#      a  b  c
# p_1  1  0  0
# p_2  1  1  0
# p_3  0  1  1
# p_4  0  1  0

但是有40,000列

我正在寻找一种向量化的方式将布尔运算and应用于结果系列:

a & b = ab -> 1 or True    a & c = ac -> 0 or False
1   0   0                  1   0   0
1   1   0                  1   0   0
0   1   1                  0   1   0
0   1   0                  0   0   0

目前我只能用一个for循环得到一个丑陋的解决方案:

res = pd.Series(index=['a&a', 'a&b', 'a&c'])
for i in range(3):
  res[i] = (tcd.iloc[:, 0] & tcd.iloc[:, i]).any()

res 
aa    1
ab    1
ac    0

通过B.M.的回答,我得到了以下内容。
def get_shared_p(tcd, i):
    res = (tcd.iloc[:, i][:, None] & tcd).any()
    res.index += '&_{}'.format(i)
    return res

res = pd.DataFrame(columns=range(cols), index=range(cols))
for col_i in range(cols):
    res.iloc[:, col_i] = list(get_shared_p(tcd, col_i))

print res
#        0     1      2
# 0   True  True  False
# 1   True  True   True
# 2  False  True   True

我们可能可以避免使用这个新的for循环。
3个回答

4
你可以使用 np.logical_andNumPy的广播功能
例如,你可以将第一列和整个矩阵分别定义为xy:
import numpy as np

x = tcd.as_matrix()
y = tcd.a.values.reshape((len(tcd), 1))

现在,使用广播,找到xy的逻辑与,并将其放置在and_中:

and_ = np.logical_and(x, y)

最后,查找是否有任何行中的任何列为 true:

>>> np.sum(and_) > 0
array([ True,  True, False], dtype=bool)

3
使用[:, None]来对齐数据并强制广播:
In[1] : res=(tcd.a[:,None] & tcd).any(); res.index+='&a'; res

Out[1]:
a&a     True
b&a     True
c&a    False
dtype: bool

太棒了 @b-m!顺便问一下,我们能否使用同样的方法来获取 &a、&b、&c 的交叉矩阵或 &_0、&_1、&2 的交叉矩阵? - user3313834
如果我理解正确,res=(tcd.T.p_1[:,None] & tcd.T).any();res.index+='&p_1';res - B. M.
1
我认为在高维空间中并不那么简单。一个解决方案:u=tcd.values.T;pd.DataFrame((u[:,None] & u).any(2),tcd.columns,tcd.columns) - B. M.

1
我会通过以下方式解决这个问题:

import pandas as pd
import numpy as np
from itertools import combinations

tcd = pd.DataFrame({
 'a': {'p_1': 1, 'p_2': 1, 'p_3': 0, 'p_4': 0},
 'b': {'p_1': 0, 'p_2': 1, 'p_3': 1, 'p_4': 1},
 'c': {'p_1': 0, 'p_2': 0, 'p_3': 1, 'p_4': 0}})

for c in combinations(tcd.columns, 2):
    tcd[c[0]+c[1]] = np.logical_and(tcd[c[0]], tcd[c[1]])

print(cd)

带有输出的:

     a  b  c     ab     ac     bc
p_1  1  0  0  False  False  False
p_2  1  1  0   True  False  False
p_3  0  1  1  False  False   True
p_4  0  1  0  False  False  False

我必须说,这看起来会非常慢。 - Ami Tavory

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