报告 difference/change 两个相同形状的数据帧之间的值
Report difference/change in values between two dataFrames of identical shape
上下文是我想比较两个 df 并找出差异。
这里的 df 和 df2 有一点不同:
df = pd.DataFrame({'a': range(3),
'b': range(3)})
df2 = df.copy()
df2.iloc[1,1] = 100
比较它们会产生相同形状的二维布尔 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的一般情况下,我认为有两种情况:
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
df很大,大家可以看看:
index column df_value df2_value
0 a 0.0 100
1 b 1.0 100
@U9-Forward 的回答非常适用于情况 1,并且只有一个为真。
@coldspeed 提供了一个全面的解决方案。谢谢!
使用条件然后dropna
:
print(df[df!=df2].dropna(how='all',axis=(0,1)))
掩码值:
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
的每一列中的值不同,那么像 agg
和 dropna
这样简单的值就可以了。
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
如果需要有关索引和列的信息,请为 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 indexing
与 numpy.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
一个 numpy 解决方案:
mask = df2[df!=df2]
a = mask.values
这returns一个数组。
x = a[~np.isnan(a)].astype(int)
>>x
array([100])
您可以使用 melt,然后筛选出不同的值:
diffs = df.ne(df2).reset_index().melt(id_vars=['index'])
>>> diffs[diffs['value'].eq(True)].iloc[:, :-1].reset_index(drop=True)
index variable
0 1 b
上下文是我想比较两个 df 并找出差异。
这里的 df 和 df2 有一点不同:
df = pd.DataFrame({'a': range(3),
'b': range(3)})
df2 = df.copy()
df2.iloc[1,1] = 100
比较它们会产生相同形状的二维布尔 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的一般情况下,我认为有两种情况:
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
df很大,大家可以看看:
index column df_value df2_value 0 a 0.0 100 1 b 1.0 100
@U9-Forward 的回答非常适用于情况 1,并且只有一个为真。
@coldspeed 提供了一个全面的解决方案。谢谢!
使用条件然后dropna
:
print(df[df!=df2].dropna(how='all',axis=(0,1)))
掩码值:
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
的每一列中的值不同,那么像 agg
和 dropna
这样简单的值就可以了。
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
如果需要有关索引和列的信息,请为 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 indexing
与 numpy.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
一个 numpy 解决方案:
mask = df2[df!=df2]
a = mask.values
这returns一个数组。
x = a[~np.isnan(a)].astype(int)
>>x
array([100])
您可以使用 melt,然后筛选出不同的值:
diffs = df.ne(df2).reset_index().melt(id_vars=['index'])
>>> diffs[diffs['value'].eq(True)].iloc[:, :-1].reset_index(drop=True)
index variable
0 1 b