81

この形式の 2 つのデータフレームがあるとします (それらdf1を および と呼びますdf2)。

+------------------------+------------------------+--------+
|        user_id         |      business_id       | rating |
+------------------------+------------------------+--------+
| rLtl8ZkDX5vH5nAx9C3q5Q | eIxSLxzIlfExI6vgAbn2JA |      4 |
| C6IOtaaYdLIT5fWd7ZYIuA | eIxSLxzIlfExI6vgAbn2JA |      5 |
| mlBC3pN9GXlUUfQi1qBBZA | KoIRdcIfh3XWxiCeV1BDmA |      3 |
+------------------------+------------------------+--------+

user_idと に共通するすべての行のデータフレームを取得しようとしていdf1ますdf2。(つまり、 auser_idが と の両方df1にある場合df2、出力データフレームに 2 つの行を含めます)

これにアプローチする方法はたくさん考えられますが、どれも扱いにくいと思います。たとえば、各データフレームですべての一意user_idの を見つけ、それぞれのセットを作成し、それらの交点を見つけ、結果のセットで 2 つのデータフレームをフィルター処理し、フィルター処理された 2 つのデータフレームを連結することができます。

それが最善のアプローチかもしれませんが、Pandas が賢いことはわかっています。これを行う簡単な方法はありますか?私は見ましたmergeが、それは私が必要としているものではないと思います。

4

3 に答える 3

112

My understanding is that this question is better answered over in this post.

But briefly, the answer to the OP with this method is simply:

s1 = pd.merge(df1, df2, how='inner', on=['user_id'])

Which gives s1 with 5 columns: user_id and the other two columns from each of df1 and df2.

于 2015-05-29T17:47:24.753 に答える
16

私があなたを正しく理解していれば、 と の組み合わせを使用できSeries.isin()ますDataFrame.append()

In [80]: df1
Out[80]:
   rating  user_id
0       2  0x21abL
1       1  0x21abL
2       1   0xdafL
3       0  0x21abL
4       4  0x1d14L
5       2  0x21abL
6       1  0x21abL
7       0   0xdafL
8       4  0x1d14L
9       1  0x21abL

In [81]: df2
Out[81]:
   rating      user_id
0       2      0x1d14L
1       1    0xdbdcad7
2       1      0x21abL
3       3      0x21abL
4       3      0x21abL
5       1  0x5734a81e2
6       2      0x1d14L
7       0       0xdafL
8       0      0x1d14L
9       4  0x5734a81e2

In [82]: ind = df2.user_id.isin(df1.user_id) & df1.user_id.isin(df2.user_id)

In [83]: ind
Out[83]:
0     True
1    False
2     True
3     True
4     True
5    False
6     True
7     True
8     True
9    False
Name: user_id, dtype: bool

In [84]: df1[ind].append(df2[ind])
Out[84]:
   rating  user_id
0       2  0x21abL
2       1   0xdafL
3       0  0x21abL
4       4  0x1d14L
6       1  0x21abL
7       0   0xdafL
8       4  0x1d14L
0       2  0x1d14L
2       1  0x21abL
3       3  0x21abL
4       3  0x21abL
6       2  0x1d14L
7       0   0xdafL
8       0  0x1d14L

これは本質的に、慣用的な方法を使用して、「ぎこちない」と説明したアルゴリズムですpandas。行インデックスが重複していることに注意してください。また、行インデックスが重複していない場合df1df2つまり、

In [93]: df1.index & df2.index
Out[93]: Int64Index([], dtype='int64')

実際、行インデックスが等しくない場合、期待される出力は得られません。

于 2013-10-27T14:15:13.493 に答える
4

SQL では、この問題はいくつかの方法で解決できます。

select * from df1 where exists (select * from df2 where df2.user_id = df1.user_id)
union all
select * from df2 where exists (select * from df1 where df1.user_id = df2.user_id)

または参加してからピボットを解除します(SQLサーバーで可能)

select
    df1.user_id,
    c.rating
from df1
    inner join df2 on df2.user_i = df1.user_id
    outer apply (
        select df1.rating union all
        select df2.rating
    ) as c

2番目のものは、パンダで次のように書くことができます:

>>> df1 = pd.DataFrame({"user_id":[1,2,3], "rating":[10, 15, 20]})
>>> df2 = pd.DataFrame({"user_id":[3,4,5], "rating":[30, 35, 40]})
>>>
>>> df4 = df[['user_id', 'rating_1']].rename(columns={'rating_1':'rating'})
>>> df = pd.merge(df1, df2, on='user_id', suffixes=['_1', '_2'])
>>> df3 = df[['user_id', 'rating_1']].rename(columns={'rating_1':'rating'})
>>> df4 = df[['user_id', 'rating_2']].rename(columns={'rating_2':'rating'})
>>> pd.concat([df3, df4], axis=0)
   user_id  rating
0        3      20
0        3      30
于 2013-10-27T14:38:43.390 に答える