使用像这样的数据
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
(但有40e3列)
我寻找一种矢量化的方法将布尔和放在结果系列中:
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 循环。
答案 0 :(得分:4)
您可以使用np.logical_and
和numpy's broadcasting。
假设您将x
和y
分别定义为第一列和整个矩阵:
import numpy as np
x = tcd.as_matrix()
y = tcd.a.values.reshape((len(tcd), 1))
现在,使用广播,找到x
和y
的逻辑,并将其放在and_
中:
and_ = np.logical_and(x, y)
最后,查找任何列中的任何行是否为真:
>>> np.sum(and_) > 0
array([ True, True, False], dtype=bool)
答案 1 :(得分: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
答案 2 :(得分: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