报告形状相同的两个数据框之间的值差异/变化

时间:2019-01-06 07:21:29

标签: python pandas dataframe mask

上下文是我想比较两个df并找出差异。

这里的df和df2差别很小:

df = pd.DataFrame({'a': range(3),
                   'b': range(3)})

df2 = df.copy()
df2.iloc[1,1] = 100

比较它们会产生相同形状的2D布尔df:

df != df2
Out[28]: 
       a      b
0  False  False
1  False   True
2  False  False

我尝试提取与True对应的元素,但其他元素(我不希望)仍然以NaN出现

df[df != df2]
Out[29]: 
    a    b
0 NaN  NaN
1 NaN  1.0
2 NaN  NaN

如何仅提取与True和索引相对应的元素(所以我知道df中的位置):

df[df != df2] # somehow?
Out[30]: 
    b
1 1.0

更新:上面的示例只有一个True。在具有多个True的一般情况下,我认为有两种情况:

  1. df很小,您可能想看看:

    df = pd.DataFrame({'a': range(3),
                       'b': range(3)})
    
    df2 = df.copy()
    df2.iloc[0,0] = 100
    df2.iloc[1,1] = 100
    
    df[df!=df2].dropna(how='all',axis=(0,1)) # U9-Forward's answer
    Out[39]: 
         a    b
    0  0.0  NaN
    1  NaN  1.0
    
  2. df很大,您可能想看看:

    index    column   df_value     df2_value
        0         a        0.0           100
        1         b        1.0           100
    

@ U9-Forward的答案在情况1以及只有一个True的情况下效果很好。

@coldspeed提供了全面的解决方案。谢谢!

5 个答案:

答案 0 :(得分:3)

屏蔽值:

df.values[df != df2]
# array([1])

该如何处理?

df2.at[0, 'a'] = 100

df
   a  b
0  0  0
1  1  1
2  2  2

df2
     a    b
0  100    0
1    1  100
2    2    2

df != df2 
       a      b
0   True  False
1  False   True
2  False  False

df.values[df != df2]
# array([0, 1])

# in the other answer
df[df!=df2].dropna(how='all',axis=(0,1))
     a    b
0  0.0  NaN
1  NaN  1.0

所需的输出是什么?


如果您只是df的每一列中的值都不同,则类似aggdropna这样的简单操作就可以。

df[df != df2].agg(lambda x: x.dropna().tolist())

a    [0.0]
b    [1.0]
dtype: object

如果需要索引和列,请使用melt

u = df2.reset_index().melt('index')
v = df.reset_index().melt('index')

u[u['value'] != v['value']]
   index variable  value
0      0        a    100
4      1        b    100

或者,使用np.nonzero对numpy进行此操作-真值为非零,这些索引将返回。

m = (df != df2).values
idx, cols = np.nonzero(m)

pd.DataFrame({
    'index': df.index.values[idx],
    'column': df.columns.values[cols],
    'value_1': df.values[m],
    'value_2': df2.values[m]
})

   index column  value_1  value_2
0      0      a        0      100
1      1      b        1      100

答案 1 :(得分:2)

使用条件,然后输入dropna

print(df[df!=df2].dropna(how='all',axis=(0,1)))

答案 2 :(得分:1)

如果要获取有关索引和列的信息,请为MultiIndex Series添加stack

df = pd.DataFrame({'a': range(3),
                   'b': range(3)})

df2 = df.copy()
df2.iloc[1,1] = 100
df2.iloc[0,0] = 100

s = df.stack()
s2 = df2.stack()
out = s[s != s2].rename_axis(['idx','col']).reset_index(name='val')
print (out)
   idx col  val
0    0   a    0
1    1   b    1

out2 = s2[s != s2].rename_axis(['idx','col']).reset_index(name='val')
print (out2)
   idx col  val
0    0   a  100
1    1   b  100

或将numpy indexingnumpy.where一起用于True值的索引:

mask = df != df2
a = np.where(mask)

out = pd.DataFrame({'idx': df.index.values[a[0]],
                    'cols': df.columns.values[a[1]],
                    'vals_df': df.values[mask],
                    'vals_df2': df2.values[mask]})
print (out)
   idx cols  vals_df  vals_df2
0    0    a        0       100
1    1    b        1       100

答案 3 :(得分:1)

numpy解决方案:

mask = df2[df!=df2]
a = mask.values

这将返回一个数组。

x = a[~np.isnan(a)].astype(int)
>>x
array([100])

答案 4 :(得分:1)

您可以使用melt,然后为不同的值进行过滤:

viewWillAppear: