web-dev-qa-db-ja.com

パンダ:2つのデータフレームの差分

サイズが異なる2つのデータフレームを行ごとに比較し、一致しない行を印刷する必要があります。次の2つを見てみましょう。

df1 = DataFrame({
'Buyer': ['Carl', 'Carl', 'Carl'],
'Quantity': [18, 3, 5, ]})

df2 = DataFrame({
'Buyer': ['Carl', 'Mark', 'Carl', 'Carl'],
'Quantity': [2, 1, 18, 5]})

Df2で行単位でdf1にない行を印刷する最も効率的な方法は何ですか?

Buyer     Quantity 
Carl         2
Mark         1

重要:行を持ちたくない:

Buyer     Quantity 
Carl         3

差分に含まれる:

私はすでに試しました: 行ごとに異なる長さの2つのデータフレームを比較し、各行に同じ値の列を追加 および 2つのPandasデータフレームの並べて出力-違いを強調表示

しかし、これらは私の問題と一致しません。

ありがとうございました

アンディ

36
Andy

merge メソッド 'outer'を使用して2つのdfを渡し、param indicator=Trueを渡すと、行が両方に存在するかどうかがわかります/左のみ/右のみ、その後、マージされたdfをフィルターできます。

In [22]:
merged = df1.merge(df2, indicator=True, how='outer')
merged[merged['_merge'] == 'right_only']

Out[22]:
  Buyer  Quantity      _merge
3  Carl         2  right_only
4  Mark         1  right_only
84
EdChum
diff = set(Zip(df2.Buyer, df2.Quantity)) - set(Zip(df1.Buyer, df1.Quantity))

これが頭に浮かんだ最初の解決策です。その後、差分セットを表示のためにDFに戻すことができます。

6
Shovalt

あなたはこれが最高だと思うかもしれません:

df2[ ~df2.isin(df1)].dropna()
4
A. Nadjar

新しいバイヤーを他のdfに追加することだけに関心がある場合は、次を試してください。

df_delta=df2[df2['Buyer'].apply(lambda x: x not in df1['Buyer'].values)]
2
Yasir

@EdChumの答えは自明です。ただし、not 'both'条件を使用する方が理にかなっており、比較の順序を気にする必要はありません。これが実際のdiffのはずです。あなたの質問に答えるために:

merged = df1.merge(df2, indicator=True, how='outer')
merged.loc = [merged['_merge'] != 'both']
0
Shayan Amani