pandas 在数据框之间配对每行,保留那些没有配对的数据框

7gyucuyw  于 6个月前  发布在  其他
关注(0)|答案(2)|浏览(94)

如果在df 1中我有一个有3个示例的对,而df 2中我只有2个示例,我将只保留那些没有对的示例。

df_1 = pd.DataFrame(data={'ID':[A, A, A, A,B,B,B,D], 'Value':[1, 1, 1, 2, 1, 1, 2,3]})
df_2 = pd.DataFrame(data={'ID':[A,A,A,B,B,C], 'Value':[1,1,2,1,2,4]})

字符串
结果:

remaining_df = pd.DataFrame(data={'ID':[A,B,B,C,D], 'Value':[1,1,2,4,3]})


我想连接ID和值,然后创建一个枢轴,然后计数连接的文本,我还没有任何,我仍然在探索,如果可能的话,或者有人给予我一个想法/指导我使用什么方法。

c9x0cxw0

c9x0cxw01#

我认为我们可以简单地使用MultiIndex如下:

# setup
A, B, C, D = 'ABCD'
df1 = pd.DataFrame(data={'ID':[A, A, A, A,B,B,B,D], 'Value':[1, 1, 1, 2, 1, 1, 2,3]})
df2 = pd.DataFrame(data={'ID':[A,A,A,B,B,C], 'Value':[1,1,2,1,2,4]})

idval = ['ID', 'Value']  # because I'm lazy
a = df1.assign(k=df1.groupby(idval).cumcount())
b = df2.assign(k=df2.groupby(idval).cumcount())
df = pd.MultiIndex.from_frame(
    a
).symmetric_difference(
    pd.MultiIndex.from_frame(b)
).to_frame(index=False).drop('k', axis=1)

>>> df
  ID  Value
0  A      1
1  B      1
2  C      4
3  D      3

字符串

说明

正如@Furas正确地说的那样,首先想到的是.groupby(['ID', 'Value'])。在这个答案中,我们使用cumcount(),它只是在每个组中累积计数。换句话说:

>>> a
  ID  Value  k
0  A      1  0
1  A      1  1
2  A      1  2
3  A      2  0
4  B      1  0
5  B      1  1
6  B      2  0
7  D      3  0


然后,我们使用MultiIndex来做一个对称差分(快速)。为了使用它,我们将每个帧(ab及其k计数器)转换为MultiIndex,然后我们取对称差分,并将结果“水合”回一个帧。整个操作应该相当快。

gz5pxeao

gz5pxeao2#

编辑:

现在我发现我的答案有一些问题。对于你的例子,它工作正常,但如果我们在第一个DataFrame中添加另一个A1,那么它在结果中将其减少为单个A1,但它应该给予两个A1,A1
这个版本不能用ie.cumsum()修复,因为它确实需要像其他答案一样的MultiIndex
但我保留它,也许有些元素会对某人有用。
我的第一个想法是使用.groupby(["ID", "Value"])将元素(在每个子帧中)与相同的IDValue分组,并使用.size()对它们进行计数-它给出两个Series

series1 = df_1.groupby(["ID", "Value"]).size()
series2 = df_2.groupby(["ID", "Value"]).size()

个字符
稍后它需要减去这些Series--但是使用s1 - s2它为值CD给出值NaN,因为它们只存在于一个Series中。它需要.subtract(... fill_value=0)来填充缺失的元素。
它需要.abs()将负值转换为正值。

series = series1.subtract(series2, fill_value=0)
series = series.abs()
ID  Value
A   1        1.0
    2        0.0
B   1        1.0
    2        0.0
C   4        1.0
D   3        1.0
dtype: float64

的字符串
现在,它需要放弃结果,这给0

series = series[ series[0] != 0 ]
ID  Value
A   1        1.0
B   1        1.0
C   4        1.0
D   3        1.0
dtype: float64

的字符串
最后,它需要清理它-重置索引,删除具有size的列(列0)。

df = series.reset_index().drop(columns=[0])
ID  Value
0  A      1
1  B      1
2  C      4
3  D      3

完整的工作代码:

import pandas as pd

df_1 = pd.DataFrame(data={'ID':["A","A","A","A","B","B","B","D"], 'Value':[1, 1, 1, 2, 1, 1, 2,3]})
df_2 = pd.DataFrame(data={'ID':["A","A","A","B","B","C"], 'Value':[1,1,2,1,2,4]})

series1 = df_1.groupby(["ID", "Value"]).size()   # Series
series2 = df_2.groupby(["ID", "Value"]).size()   # Series

print('\n--- series1 groupby.size ---\n')
print(series1)
print('\n--- series2 groupby.size ---\n')
print(series2)

series = series1.subtract(series2, fill_value=0).abs()  # Series

print('\n--- series subtract.abs ---\n')
print(series)

series = series[ series != 0 ]  # Series

print('\n--- series drop ---\n')
print(series)

df = series.reset_index().drop(columns=[0])  # DataFrame

print('\n--- df clean ---\n')

print(df)


测试结果:

--- series1 groupby.size ---

ID  Value
A   1        3
    2        1
B   1        2
    2        1
D   3        1
dtype: int64

--- series2 groupby.size ---

ID  Value
A   1        2
    2        1
B   1        1
    2        1
C   4        1
dtype: int64

--- series subtract.abs ---

ID  Value
A   1        1.0
    2        0.0
B   1        1.0
    2        0.0
C   4        1.0
D   3        1.0
dtype: float64

--- series drop ---

ID  Value
A   1        1.0
B   1        1.0
C   4        1.0
D   3        1.0
dtype: float64

--- df clean ---

  ID  Value
0  A      1
1  B      1
2  C      4
3  D      3

相关问题