我有一个看起来像这样的DataFrame:
FirstDF=
C
A B
'a' 'blue' 43
'green' 59
'b' 'red 56
'c' 'green' 80
'orange' 72
其中A和B设置为索引。我也有一个看起来像这样的DataFrame:
SecondDF=
A B
0 'a' 'green'
1 'b' 'red'
2 'c' 'green'
有没有一种方法可以直接查询第一个DataFrame和最后一个DataFrame,并获得如下所示的输出?
C
59
56
80
我通过遍历第二个DataFrame来做到这一点,如下所示,但是我想使用pandas逻辑而不是for循环来实现。
data=[]
for i in range(SecondDF.shape[0]):
data.append(FirstDF.loc[tuple(SecondDF.iloc[i])])
data=pd.Series(data)
答案 0 :(得分:2)
将merge
与参数left_index
和right_on
一起使用:
df = FirstDF.merge(SecondDF, left_index=True, right_on=['A','B'])['C'].to_frame()
print (df)
C
0 59
1 56
2 80
另一个isin
个MultiIndex
中并通过boolean indexing
进行过滤的解决方案:
mask = FirstDF.index.isin(SecondDF.set_index(['A','B']).index)
#alternative solution
#mask = FirstDF.index.isin(list(map(tuple,SecondDF[['A','B']].values.tolist())))
df = FirstDF.loc[mask, ['C']].reset_index(drop=True)
print (df)
C
0 59
1 56
2 80
详细信息:
print (FirstDF.loc[mask, ['C']])
C
A B
'a' 'green' 59
'b' 'red' 56
'c' 'green' 80
编辑:
您可以将merge
与外部联接和indicator=True
参数一起使用,然后按boolean indexing
进行过滤:
df1=FirstDF.merge(SecondDF, left_index=True, right_on=['A','B'], indicator=True, how='outer')
print (df1)
C A B _merge
2 43 'a' 'blue' left_only
0 59 'a' 'green' both
1 56 'b' 'red' both
2 80 'c' 'green' both
2 72 'c' 'orange' left_only
mask = df1['_merge'] != 'both'
df1 = df1.loc[mask, ['C']].reset_index(drop=True)
print (df1)
C
0 43
1 72
对于第二个解决方案,用~
反转布尔值掩码:
mask = FirstDF.index.isin(SecondDF.set_index(['A','B']).index)
#alternative solution
#mask = FirstDF.index.isin(list(map(tuple,SecondDF[['A','B']].values.tolist())))
df = FirstDF.loc[~mask, ['C']].reset_index(drop=True)
print (df)
C
0 43
1 72
答案 1 :(得分:2)
FirstDF.loc[zip(SecondDF['A'],SecondDF['B']),]
说明:-
想法是从第二个数据帧中获取索引,并在第一个数据帧上使用它们。 对于多索引,您可以传递索引的元组来获取行。
FirstDF.loc[('bar','two'),]
将为您提供所有第一个索引为'bar并且第二个索引为'two'的行。
FirstDF.loc[(SecondDF['A'],SecondDF['B']),]
直接从SecondDF中获取您想要的那些索引,但是要注意的是它将获取'A'和'B'的所有组合。因此,添加zip将仅使用SecondDF同一行中一部分的索引
答案 2 :(得分:0)
您可以使用merge获得结果;
In [35]: df1
Out[35]:
A B C
0 a blue 43
1 a green 59
2 b red 56
3 c green 80
4 c orange 72
In [36]: df2
Out[36]:
A B
0 a green
1 b red
2 c green
In [37]: pd.merge(df1, df2, on=['A', 'B'])['C']
Out[37]:
0 59
1 56
2 80
Name: C, dtype: int64
答案 3 :(得分:0)
好的,我找到了答案:
tuple_list = list(map(tuple,SecondDF.values))
insDF = FirstDF.loc[tuple_list].dropna()
outsDF = FirstDF.loc[~FirstDF.index.isin(tuple_list)]
这将提供FirstDF中的值和非值。 之所以使用dropna方法,是因为该查询将SecondDF中不在FirstDF中的值留为NaN,因此应将其删除。