在python中,如何从另一个数据帧的子集交集中减去一个数据帧?

在python中,如何从另一个数据帧的子集交集中减去一个数据帧?,python,pandas,dataframe,subtraction,Python,Pandas,Dataframe,Subtraction,我对python中的以下数据帧有一个简单的定义: 数据帧1 数据帧2 您可以看到dataframe2包含dataframe1的多索引,但它也包含额外的多索引,如horse和cat。Dataframe 2也不包含Dataframe 1的所有列,因为您可以看到它没有包含第3列 我想从dataframe 1中减去dataframe 2,这样函数就只减去两者通用的数据,而忽略其余的数据,得到的dataframe是dataframe 2的形状 有人知道pandas是否提供了一种内置的方法,或者我需要自己构

我对python中的以下数据帧有一个简单的定义:

数据帧1 数据帧2 您可以看到dataframe2包含dataframe1的多索引,但它也包含额外的多索引,如horse和cat。Dataframe 2也不包含Dataframe 1的所有列,因为您可以看到它没有包含第3列

我想从dataframe 1中减去dataframe 2,这样函数就只减去两者通用的数据,而忽略其余的数据,得到的dataframe是dataframe 2的形状

有人知道pandas是否提供了一种内置的方法,或者我需要自己构造一个函数吗。如果是这样,你能给我指出正确的方向吗?非常感谢您的任何建议。多谢各位

注意:这个问题与我发布的另一个问题类似,只是我不想比较这些问题,而是想做一个减法算术运算。

IIUC:

In [24]: r = d1.sub(d2, axis=0)

In [25]: r.loc[r.index.intersection(d2.index)]
Out[25]:
             1    2   3    4    5
dog dog   -1.0  1.0 NaN  0.0  1.0
    fox    1.0 -1.0 NaN  0.0 -1.0
    horse  NaN  NaN NaN  NaN  NaN
    jumps  0.0 -1.0 NaN  0.0  0.0
    the    0.0  1.0 NaN  0.0  0.0
fox cat    NaN  NaN NaN  NaN  NaN
    dog    0.0  0.0 NaN  1.0  1.0
    fox    0.0 -1.0 NaN  0.0 -1.0
    over   0.0  1.0 NaN  0.0  0.0
    the    0.0 -1.0 NaN  1.0  0.0

我相信你只是想要这样的东西:

In [23]: (df2 - df1.drop('3', axis=1)).fillna(df2).dropna()
Out[23]:
             1    2    4    5
dog dog    1.0 -1.0  0.0 -1.0
    fox   -1.0  1.0  0.0  1.0
    horse  1.0  0.0  1.0  0.0
    jumps  0.0  1.0  0.0  0.0
    the    0.0 -1.0  0.0  0.0
fox cat    0.0  0.0  1.0  0.0
    dog    0.0  0.0 -1.0 -1.0
    fox    0.0  1.0  0.0  1.0
    over   0.0 -1.0  0.0  0.0
    the    0.0  1.0 -1.0  0.0
熊猫已经在索引上自动对齐了,这是它神奇的一部分,但是你只需要智能地填充/删除NAN

编辑 哎哟,你真的想要
df1-df2
,但是对于
df2
的形状,从那以后再加一点技巧
fillna(df1)
会阻止我们删除正确的行,但是,你可以使用乘-1

In [25]: (df2 - df1.drop('3', axis=1)).fillna(df2).dropna() * -1
Out[25]:
             1    2    4    5
dog dog   -1.0  1.0 -0.0  1.0
    fox    1.0 -1.0 -0.0 -1.0
    horse -1.0 -0.0 -1.0 -0.0
    jumps -0.0 -1.0 -0.0 -0.0
    the   -0.0  1.0 -0.0 -0.0
fox cat   -0.0 -0.0 -1.0 -0.0
    dog   -0.0 -0.0  1.0  1.0
    fox   -0.0 -1.0 -0.0 -1.0
    over  -0.0  1.0 -0.0 -0.0
    the   -0.0 -1.0  1.0 -0.0
或者,如果这些负零困扰您:

In [31]: (-df2 + df1.drop('3', axis=1)).fillna(-df2).dropna()
Out[31]:
             1    2    4    5
dog dog   -1.0  1.0  0.0  1.0
    fox    1.0 -1.0  0.0 -1.0
    horse -1.0  0.0 -1.0  0.0
    jumps  0.0 -1.0  0.0  0.0
    the    0.0  1.0  0.0  0.0
fox cat    0.0  0.0 -1.0  0.0
    dog    0.0  0.0  1.0  1.0
    fox    0.0 -1.0  0.0 -1.0
    over   0.0  1.0  0.0  0.0
    the    0.0 -1.0  1.0  0.0

让我们做一些类似的事情

id=df2.index.values.tolist()
dd=df1.loc[list(set(df1.index.values.tolist())&set(id))]
(df2-dd).combine_first(df2).dropna(1)

             1    2    4    5
dog dog    1.0 -1.0  0.0 -1.0
    fox   -1.0  1.0  0.0  1.0
    horse  1.0  0.0  1.0  0.0
    jumps  0.0  1.0  0.0  0.0
    the    0.0 -1.0  0.0  0.0
fox cat    0.0  0.0  1.0  0.0
    dog    0.0  0.0 -1.0 -1.0
    fox    0.0  1.0  0.0  1.0
    over   0.0 -1.0  0.0  0.0
    the    0.0  1.0 -1.0  0.0

使用
pd.DataFrame.align
和参数
'internal'
将两个数据帧减少为仅通用索引。然后将结果传递给
pd.DataFrame.sub

pd.DataFrame.sub(*df1.align(df2, 'inner'))

           1  2  4  5
dog dog   -1  1  0  1
    fox    1 -1  0 -1
    jumps  0 -1  0  0
    the    0  1  0  0
fox dog    0  0  1  1
    fox    0 -1  0 -1
    over   0  1  0  0
    the    0 -1  1  0

用两行写的

a, b = df1.align(df2, 'inner')
a - b

您能否提供一个更可行的示例,即人们实际上可以复制粘贴运行的内容?否则,很多人会转向其他问题。诚然,对于多索引来说,这可能很棘手。看这个:啊,是的,很好idea@juanpa.arrivillaga, ;-)@MaxU干得好,先生。@juanpa.arrivillaga,谢谢:)@juanpa.arrivillaga由于df2是可变的,所以没有必要将列“3”作为缺失的列。有什么想法吗?@Elisha512你可以做一些事情,比如
missing=df1.columns.difference(df2.columns)
,然后把它传递给@juanpa.arrivillaga和(-df2+df1.drop(missing,axis=1)).fillna(-df2)。dropna()正确吗?@Elisha512是的,这就是我的意思。你也有可以使用的rsub!我从来没有见过“align”方法,因为@Psidom给我展示了它。非常好。可以指定轴、填充值以及内部或外部。不确定是向左还是向右。
pd.DataFrame.sub(*df1.align(df2, 'inner'))

           1  2  4  5
dog dog   -1  1  0  1
    fox    1 -1  0 -1
    jumps  0 -1  0  0
    the    0  1  0  0
fox dog    0  0  1  1
    fox    0 -1  0 -1
    over   0  1  0  0
    the    0 -1  1  0
a, b = df1.align(df2, 'inner')
a - b