注意:这个问题的灵感来自于另一篇文章中讨论的想法:DataFrame algebra in Pandas
假设我有两个数据框 A
和 B
,对于某些列 col_name
,它们的值为:
A[col_name] | B[col_name]
--------------| ------------
1 | 3
2 | 4
3 | 5
4 | 6
我想根据 col_name
计算 A
和 B
之间的集合差。此操作的结果应该是:
A
的行,其中 A[col_name]
与 B[col_name]
中的任何条目均不匹配。
下面是上述示例的结果(还显示了 A
的其他列):
A[col_name] | A[other_column_1] | A[other_column_2]
------------+-------------------|------------------
1 | 'foo' | 'xyz' ....
2 | 'bar' | 'abc'
请记住,A[col_name]
和 B[col_name]
中的某些条目可能包含值 np.NaN
。我想将这些条目视为未定义但不同,即设置的差异应该返回它们。
我怎样才能在 Pandas 中做到这一点? (推广到多列上的差异也很好)
最佳答案
一种方法是使用系列 isin
方法:
In [11]: df1 = pd.DataFrame([[1, 'foo'], [2, 'bar'], [3, 'meh'], [4, 'baz']], columns = ['A', 'B'])
In [12]: df2 = pd.DataFrame([[3, 'a'], [4, 'b']], columns = ['A', 'C'])
现在您可以检查 df1['A']
中的每个项目是否在 df2['A']
中:
In [13]: df1['A'].isin(df2['A'])
Out[13]:
0 False
1 False
2 True
3 True
Name: A, dtype: bool
In [14]: df1[~df1['A'].isin(df2['A'])] # not in df2['A']
Out[14]:
A B
0 1 foo
1 2 bar
我认为这也能满足您对 NaN 的需求:
In [21]: df1 = pd.DataFrame([[1, 'foo'], [np.nan, 'bar'], [3, 'meh'], [np.nan, 'baz']], columns = ['A', 'B'])
In [22]: df2 = pd.DataFrame([[3], [np.nan]], columns = ['A'])
In [23]: df1[~df1['A'].isin(df2['A'])]
Out[23]:
A B
0 1.0 foo
1 NaN bar
3 NaN baz
注意:对于大型框架,可能值得将这些列设为索引(以执行 the other question 中讨论的连接)。
更一般性
合并两个或多个列的一种方法是使用虚拟列:
In [31]: df1 = pd.DataFrame([[1, 'foo'], [np.nan, 'bar'], [4, 'meh'], [np.nan, 'eurgh']], columns = ['A', 'B'])
In [32]: df2 = pd.DataFrame([[np.nan, 'bar'], [4, 'meh']], columns = ['A', 'B'])
In [33]: cols = ['A', 'B']
In [34]: df2['dummy'] = df2[cols].isnull().any(1) # rows with NaNs in cols will be True
In [35]: merged = df1.merge(df2[cols + ['dummy']], how='left')
In [36]: merged
Out[36]:
A B dummy
0 1 foo NaN
1 NaN bar True
2 4 meh False
3 NaN eurgh NaN
bool 值存在于 df2 中,True 在合并列之一中具有 NaN。按照您的规范,我们应该删除那些错误的:
In [37]: merged.loc[merged.dummy != False, df1.columns]
Out[37]:
A B
0 1 foo
1 NaN bar
3 NaN eurgh
不优雅。
关于python - 设置数据帧之间列的差异,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/22109361/