私はこのDataFrame(_df1
_)をパンダに持っています:
_df1 = pd.DataFrame(np.random.Rand(10,4),columns=list('ABCD'))
print df1
A B C D
0.860379 0.726956 0.394529 0.833217
0.014180 0.813828 0.559891 0.339647
0.782838 0.698993 0.551252 0.361034
0.833370 0.982056 0.741821 0.006864
0.855955 0.546562 0.270425 0.136006
0.491538 0.445024 0.971603 0.690001
0.911696 0.065338 0.796946 0.853456
0.744923 0.545661 0.492739 0.337628
0.576235 0.219831 0.946772 0.752403
0.164873 0.454862 0.745890 0.437729
_
別のデータフレーム(_df2
_)の行(すべての列)が_df1
_に存在するかどうかを確認したいと思います。ここに_df2
_があります:
_df2 = df1.ix[4:8]
df2.reset_index(drop=True,inplace=True)
df2.loc[-1] = [2, 3, 4, 5]
df2.loc[-2] = [14, 15, 16, 17]
df2.reset_index(drop=True,inplace=True)
print df2
A B C D
0.855955 0.546562 0.270425 0.136006
0.491538 0.445024 0.971603 0.690001
0.911696 0.065338 0.796946 0.853456
0.744923 0.545661 0.492739 0.337628
0.576235 0.219831 0.946772 0.752403
2.000000 3.000000 4.000000 5.000000
14.000000 15.000000 16.000000 17.000000
_
_df.lookup
_を使用して、一度に1つの行を検索しようとしました。私はこのようにしました:
_list1 = df2.ix[0].tolist()
cols = df1.columns.tolist()
print df1.lookup(list1, cols)
_
しかし、私はこのエラーメッセージを受け取りました:
_ File "C:\Users\test.py", line 19, in <module>
print df1.lookup(list1, cols)
File "C:\python27\lib\site-packages\pandas\core\frame.py", line 2217, in lookup
raise KeyError('One or more row labels was not found')
KeyError: 'One or more row labels was not found'
_
私は.all()
も試しました:
_print (df2 == df1).all(1).any()
_
しかし、私はこのエラーメッセージを受け取りました:
_ File "C:\Users\test.py", line 12, in <module>
print (df2 == df1).all(1).any()
File "C:\python27\lib\site-packages\pandas\core\ops.py", line 884, in f
return self._compare_frame(other, func, str_rep)
File "C:\python27\lib\site-packages\pandas\core\frame.py", line 3010, in _compare_frame
raise ValueError('Can only compare identically-labeled '
ValueError: Can only compare identically-labeled DataFrame objects
_
私もこのようにisin()
を試しました:
_print df2.isin(df1)
_
しかし、どこでもFalse
を得ましたが、これは正しくありません:
_ A B C D
False False False False
False False False False
False False False False
False False False False
False False False False
False False False False
False False False False
False False False False
False False False False
False False False False
_
別のデータフレームの行と比較することにより、DataFrameの行セットを検索することは可能ですか?
編集:_df2
_行が_df1
_にも存在する場合、それらを削除することは可能ですか?
問題の解決策の1つは、 merge を使用することです。別のデータフレーム(df2)の行(すべての列)がdf1に存在するかどうかを確認することは、2つのデータフレームの交差を決定することと同等です。これは、次の機能を使用して実現できます。
_pd.merge(df1, df2, on=['A', 'B', 'C', 'D'], how='inner')
_
たとえば、df1が
_ A B C D
0 0.403846 0.312230 0.209882 0.397923
1 0.934957 0.731730 0.484712 0.734747
2 0.588245 0.961589 0.910292 0.382072
3 0.534226 0.276908 0.323282 0.629398
4 0.259533 0.277465 0.043652 0.925743
5 0.667415 0.051182 0.928655 0.737673
6 0.217923 0.665446 0.224268 0.772592
7 0.023578 0.561884 0.615515 0.362084
8 0.346373 0.375366 0.083003 0.663622
9 0.352584 0.103263 0.661686 0.246862
_
df2は次のように定義されました。
_ A B C D
0 0.259533 0.277465 0.043652 0.925743
1 0.667415 0.051182 0.928655 0.737673
2 0.217923 0.665446 0.224268 0.772592
3 0.023578 0.561884 0.615515 0.362084
4 0.346373 0.375366 0.083003 0.663622
5 2.000000 3.000000 4.000000 5.000000
6 14.000000 15.000000 16.000000 17.000000
_
関数pd.merge(df1, df2, on=['A', 'B', 'C', 'D'], how='inner')
は以下を生成します。
_ A B C D
0 0.259533 0.277465 0.043652 0.925743
1 0.667415 0.051182 0.928655 0.737673
2 0.217923 0.665446 0.224268 0.772592
3 0.023578 0.561884 0.615515 0.362084
4 0.346373 0.375366 0.083003 0.663622
_
結果は、df1とdf2の両方にあるすべての行(すべての列)です。
列がdf1とdf2で同じでない場合、この例を変更し、列のサブセットで同じ行の値を比較することもできます。元の例を変更する場合:
_df1 = pd.DataFrame(np.random.Rand(10,4),columns=list('ABCD'))
df2 = df1.ix[4:8]
df2.reset_index(drop=True,inplace=True)
df2.loc[-1] = [2, 3, 4, 5]
df2.loc[-2] = [14, 15, 16, 17]
df2.reset_index(drop=True,inplace=True)
df2 = df2[['A', 'B', 'C']] # df2 has only columns A B C
_
次に、2つのデータフレーム間でcommon_cols = list(set(df1.columns) & set(df2.columns))
を使用して共通の列を確認し、マージします。
_pd.merge(df1, df2, on=common_cols, how='inner')
_
EDIT:新しい質問(コメント)は、最初のデータフレーム(df1)にも存在するdf2の行を識別したため、 pd.merge()の結果、df1にも存在するdf2から行をドロップする
私はdf1にも存在するdf2から行をドロップするタスクを達成するための簡単な方法を知りません。とはいえ、次のものを使用できます。
_ds1 = set(Tuple(line) for line in df1.values)
ds2 = set(Tuple(line) for line in df2.values)
df = pd.DataFrame(list(ds2.difference(ds1)), columns=df2.columns)
_
おそらくそのタスクを達成するためのより良い方法が存在しますが、私はそのようなメソッド/機能を知りません。
EDIT 2:@WR回答に示されているように、df1にも存在するdf2から行を削除する方法。
提供されるメソッドdf2[~df2['A'].isin(df12['A'])]
は、すべてのタイプの状況を考慮していません。以下のデータフレームを考慮してください。
df1:
_ A B C D
0 6 4 1 6
1 7 6 6 8
2 1 6 2 7
3 8 0 4 1
4 1 0 2 3
5 8 4 7 5
6 4 7 1 1
7 3 7 3 4
8 5 2 8 8
9 3 2 8 4
_
df2:
_ A B C D
0 1 0 2 3
1 8 4 7 5
2 4 7 1 1
3 3 7 3 4
4 5 2 8 8
5 1 1 1 1
6 2 2 2 2
_
df12:
_ A B C D
0 1 0 2 3
1 8 4 7 5
2 4 7 1 1
3 3 7 3 4
4 5 2 8 8
_
Df1にも存在するdf2から行を削除する目的で上記のDataFramesを使用すると、次のようになります。
_ A B C D
0 1 1 1 1
1 2 2 2 2
_
行(1、1、1、1)および(2、2、2、2)はdf2にあり、df1にはありません。残念ながら、提供されたメソッド(df2[~df2['A'].isin(df12['A'])]
)を使用すると次の結果になります。
_ A B C D
6 2 2 2 2
_
これは、列Aの値1が交差点DataFrame(つまり(1、0、2、3))とdf2の両方で検出され、したがって(1、0、2、3)と(1、1、 1、1)。これは、行(1、1、1、1)がdf1にないため、削除しないでください。
以下が解決策を提供すると思います。後でDataFrameをサブセットして目的の結果に使用するダミー列を作成します。
_df12['key'] = 'x'
temp_df = pd.merge(df2, df12, on=df2.columns.tolist(), how='left')
temp_df[temp_df['key'].isnull()].drop('key', axis=1)
_
@Andrew:ループを使用せずに、別のデータフレームに既に存在する1つのデータフレームの行を削除する方法を見つけたと思います(つまり、編集に応答する)これを述べてください:
この作品
両方のデータフレームの列は常に同じです-A
、B
、C
およびD
。これを念頭に置いて、Andrewのアプローチに大きく基づいて、_df2
_に存在する行を_df1
_から削除する方法を次に示します。
_common_cols = df1.columns.tolist() #generate list of column names
df12 = pd.merge(df1, df2, on=common_cols, how='inner') #extract common rows with merge
df2 = df2[~df2['A'].isin(df12['A'])]
_
行3は次のことを行います。
df2
_の行と一致しない行のみを_df1
_から抽出します。A
を選択しました。注:このメソッドは、本質的にSQL NOT IN()
と同等です。