Python Pandas-检查一个数据帧中的字符串列是否包含另一个数据帧中的一对字符串
这个问题是基于我问的另一个问题,我没有完全涵盖这个问题: 这是问题的一个修改版本 我有两个数据帧:Python Pandas-检查一个数据帧中的字符串列是否包含另一个数据帧中的一对字符串,python,pandas,string-matching,boolean-expression,Python,Pandas,String Matching,Boolean Expression,这个问题是基于我问的另一个问题,我没有完全涵盖这个问题: 这是问题的一个修改版本 我有两个数据帧: df1 = pd.DataFrame({'consumption':['squirrel ate apple', 'monkey likes apple', 'monkey banana gets', 'badger gets banana', 'giraffe eats grass', 'badger apple loves'
df1 = pd.DataFrame({'consumption':['squirrel ate apple', 'monkey likes apple',
'monkey banana gets', 'badger gets banana', 'giraffe eats grass', 'badger apple loves', 'elephant is huge', 'elephant eats banana tree', 'squirrel digs in grass']})
df2 = pd.DataFrame({'food':['apple', 'apple', 'banana', 'banana'],
'creature':['squirrel', 'badger', 'monkey', 'elephant']})
目标是测试df1.consumptions中是否存在df.food:df.Biome对
上述示例中该测试的预期答案为:
['True', 'False', 'True', 'False', 'False', 'True', 'False', 'True', 'False']
模式是:
松鼠吃苹果=正确,因为松鼠和苹果是一对。
猴子喜欢苹果=错,因为猴子和苹果不是我们要找的一对
我正在考虑构建一个成对值的数据帧字典,其中每个数据帧将用于一种生物,例如松鼠、猴子等,然后使用np.where创建布尔表达式并执行str.contains
不确定这是不是最简单的方法 考虑这种矢量化方法:
from sklearn.feature_extraction.text import CountVectorizer
vect = CountVectorizer()
X = vect.fit_transform(df1.consumption)
Y = vect.transform(df2.creature + ' ' + df2.food)
res = np.ravel(np.any((X.dot(Y.T) > 1).todense(), axis=1))
结果:
In [67]: res
Out[67]: array([ True, False, True, False, False, True, False, True, False], dtype=bool)
说明:
In [68]: pd.DataFrame(X.toarray(), columns=vect.get_feature_names())
Out[68]:
apple ate badger banana digs eats elephant gets giraffe grass huge in is likes loves monkey squirrel tree
0 1 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0
1 1 0 0 0 0 0 0 0 0 0 0 0 0 1 0 1 0 0
2 0 0 0 1 0 0 0 1 0 0 0 0 0 0 0 1 0 0
3 0 0 1 1 0 0 0 1 0 0 0 0 0 0 0 0 0 0
4 0 0 0 0 0 1 0 0 1 1 0 0 0 0 0 0 0 0
5 1 0 1 0 0 0 0 0 0 0 0 0 0 0 1 0 0 0
6 0 0 0 0 0 0 1 0 0 0 1 0 1 0 0 0 0 0
7 0 0 0 1 0 1 1 0 0 0 0 0 0 0 0 0 0 1
8 0 0 0 0 1 0 0 0 0 1 0 1 0 0 0 0 1 0
In [69]: pd.DataFrame(Y.toarray(), columns=vect.get_feature_names())
Out[69]:
apple ate badger banana digs eats elephant gets giraffe grass huge in is likes loves monkey squirrel tree
0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0
1 1 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
2 0 0 0 1 0 0 0 0 0 0 0 0 0 0 0 1 0 0
3 0 0 0 1 0 0 1 0 0 0 0 0 0 0 0 0 0 0
更新:
In [92]: df1['match'] = np.ravel(np.any((X.dot(Y.T) > 1).todense(), axis=1))
In [93]: df1
Out[93]:
consumption match
0 squirrel ate apple True
1 monkey likes apple False
2 monkey banana gets True
3 badger gets banana False
4 giraffe eats grass False
5 badger apple loves True
6 elephant is huge False
7 elephant eats banana tree True
8 squirrel digs in grass False
9 squirrel.eats/apple True # <----- NOTE
[92]中的df1['match']=np.ravel(np.any((X.dot(Y.T)>1.todense(),axis=1))
In[93]:df1
出[93]:
消费匹配
0松鼠吃了苹果真的吗
猴子喜欢假苹果
猴子香蕉成真
獾得到香蕉是假的
长颈鹿吃草是假的
5獾苹果爱真
大象是巨大的假象
大象吃香蕉树真的吗
8只松鼠在草地上挖洞
9 squirrel.eats/apple True#考虑这种矢量化方法:
from sklearn.feature_extraction.text import CountVectorizer
vect = CountVectorizer()
X = vect.fit_transform(df1.consumption)
Y = vect.transform(df2.creature + ' ' + df2.food)
res = np.ravel(np.any((X.dot(Y.T) > 1).todense(), axis=1))
结果:
In [67]: res
Out[67]: array([ True, False, True, False, False, True, False, True, False], dtype=bool)
说明:
In [68]: pd.DataFrame(X.toarray(), columns=vect.get_feature_names())
Out[68]:
apple ate badger banana digs eats elephant gets giraffe grass huge in is likes loves monkey squirrel tree
0 1 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0
1 1 0 0 0 0 0 0 0 0 0 0 0 0 1 0 1 0 0
2 0 0 0 1 0 0 0 1 0 0 0 0 0 0 0 1 0 0
3 0 0 1 1 0 0 0 1 0 0 0 0 0 0 0 0 0 0
4 0 0 0 0 0 1 0 0 1 1 0 0 0 0 0 0 0 0
5 1 0 1 0 0 0 0 0 0 0 0 0 0 0 1 0 0 0
6 0 0 0 0 0 0 1 0 0 0 1 0 1 0 0 0 0 0
7 0 0 0 1 0 1 1 0 0 0 0 0 0 0 0 0 0 1
8 0 0 0 0 1 0 0 0 0 1 0 1 0 0 0 0 1 0
In [69]: pd.DataFrame(Y.toarray(), columns=vect.get_feature_names())
Out[69]:
apple ate badger banana digs eats elephant gets giraffe grass huge in is likes loves monkey squirrel tree
0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0
1 1 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
2 0 0 0 1 0 0 0 0 0 0 0 0 0 0 0 1 0 0
3 0 0 0 1 0 0 1 0 0 0 0 0 0 0 0 0 0 0
更新:
In [92]: df1['match'] = np.ravel(np.any((X.dot(Y.T) > 1).todense(), axis=1))
In [93]: df1
Out[93]:
consumption match
0 squirrel ate apple True
1 monkey likes apple False
2 monkey banana gets True
3 badger gets banana False
4 giraffe eats grass False
5 badger apple loves True
6 elephant is huge False
7 elephant eats banana tree True
8 squirrel digs in grass False
9 squirrel.eats/apple True # <----- NOTE
[92]中的df1['match']=np.ravel(np.any((X.dot(Y.T)>1.todense(),axis=1))
In[93]:df1
出[93]:
消费匹配
0松鼠吃了苹果真的吗
猴子喜欢假苹果
猴子香蕉成真
獾得到香蕉是假的
长颈鹿吃草是假的
5獾苹果爱真
大象是巨大的假象
大象吃香蕉树真的吗
8只松鼠在草地上挖洞
9 squirrel.eats/apple True#这是我用理解和zip
注意,这将检查df1
c = df1.consumption.values.tolist()
f = df2.food.values.tolist()
a = df2.creature.values.tolist()
check = np.array([[fd in cs and cr in cs for fd, cr in zip(f, a)] for cs in c])
check.any(1)
array([ True, False, True, False, False, True, False, True, False], dtype=bool)
这是@MaxU的pandas
版本。尊重他的所作所为。。。太棒了
X = df1.consumption.str.get_dummies(' ')
Y = (df2.creature + ' ' + df2.food).str.get_dummies(' ') \
.reindex_axis(X.columns, 1, fill_value=0)
# This is where you can see which rows from `df2` (columns)
# matched with which rows from `df1` (rows)
XY = X.dot(Y.T)
print(XY)
0 1 2 3
0 2 1 0 0
1 1 1 1 0
2 0 0 2 1
3 0 1 1 1
4 0 0 0 0
5 1 2 0 0
6 0 0 0 1
7 0 0 1 2
8 1 0 0 0
# return the desired `True`s and `False`s
XY.gt(1).any(1)
0 True
1 False
2 True
3 False
4 False
5 True
6 False
7 True
8 False
dtype: bool
天真测试
这是我用理解和zip
注意,这将检查df1
c = df1.consumption.values.tolist()
f = df2.food.values.tolist()
a = df2.creature.values.tolist()
check = np.array([[fd in cs and cr in cs for fd, cr in zip(f, a)] for cs in c])
check.any(1)
array([ True, False, True, False, False, True, False, True, False], dtype=bool)
这是@MaxU的pandas
版本。尊重他的所作所为。。。太棒了
X = df1.consumption.str.get_dummies(' ')
Y = (df2.creature + ' ' + df2.food).str.get_dummies(' ') \
.reindex_axis(X.columns, 1, fill_value=0)
# This is where you can see which rows from `df2` (columns)
# matched with which rows from `df1` (rows)
XY = X.dot(Y.T)
print(XY)
0 1 2 3
0 2 1 0 0
1 1 1 1 0
2 0 0 2 1
3 0 1 1 1
4 0 0 0 0
5 1 2 0 0
6 0 0 0 1
7 0 0 1 2
8 1 0 0 0
# return the desired `True`s and `False`s
XY.gt(1).any(1)
0 True
1 False
2 True
3 False
4 False
5 True
6 False
7 True
8 False
dtype: bool
天真测试
谢谢-有一个警告-生物和食物的出现没有固定的模式。因此:Y=vect.transform(df2.biote+''+df2.food)
不起作用。抱歉,我刚刚修改了问题中的消耗值以反映这一点。@vagabond,您是否根据修改后的数据集测试了我的解决方案?;-)哇!它起作用了!有没有办法从匹配的行中提取生物和食物?我的查找数据也是100K++行。稀疏矩阵可能会消耗内存?@vagabond,稀疏矩阵非常节省内存(这是它们的主要用途)。关于提取-你能打开一个新问题并在那里做一个例子吗?嗯,是的,我可以-另一个问题是,有时文本没有空格-squirrel.eats/apple。这是URL数据。谢谢-有一个警告-生物和食物的出现没有固定的模式。因此:Y=vect.transform(df2.biote+''+df2.food)
不起作用。抱歉,我刚刚修改了问题中的消耗值以反映这一点。@vagabond,您是否根据修改后的数据集测试了我的解决方案?;-)哇!它起作用了!有没有办法从匹配的行中提取生物和食物?我的查找数据也是100K++行。稀疏矩阵可能会消耗内存?@vagabond,稀疏矩阵非常节省内存(这是它们的主要用途)。关于提取-你能打开一个新问题并在那里做一个例子吗?嗯,是的,我可以-另一个问题是,有时文本没有空格-squirrel.eats/apple。这是URL数据。