Supposons que j'ai deux images de données de ce format (appelez-les df1
et df2
):
+------------------------+------------------------+--------+
| user_id | business_id | rating |
+------------------------+------------------------+--------+
| rLtl8ZkDX5vH5nAx9C3q5Q | eIxSLxzIlfExI6vgAbn2JA | 4 |
| C6IOtaaYdLIT5fWd7ZYIuA | eIxSLxzIlfExI6vgAbn2JA | 5 |
| mlBC3pN9GXlUUfQi1qBBZA | KoIRdcIfh3XWxiCeV1BDmA | 3 |
+------------------------+------------------------+--------+
Je cherche à obtenir un cadre de données de toutes les lignes qui ont un commun user_id
dans df1
et df2
. (ie si un user_id
est dans les deux df1
et df2
, inclure les deux lignes dans la trame de données en sortie)
Je peux penser à beaucoup de façons d'aborder cela, mais elles me paraissent toutes maladroites. Par exemple, nous pourrions trouver l’unique user_id
s dans chaque cadre de données, créez un ensemble de chacun, trouvez leur intersection, filtrez les deux images avec l’ensemble obtenu et concaténez les deux images filtrées.
C’est peut-être la meilleure approche, mais je sais que Pandas est intelligent. Existe-t-il un moyen plus simple de procéder? J'ai jeté un œil sur merge
mais je ne pense pas que ce soit ce J'ai besoin de.
Si j'ai bien compris, il est préférable de répondre à cette question dans this post .
Mais brièvement, la réponse au PO avec cette méthode est simplement:
s1 = pd.merge(df1, df2, how='inner', on=['user_id'])
Ce qui donne s1 avec 5 colonnes: user_id et les deux autres colonnes de chacune de df1 et df2.
Si je vous ai bien compris, vous pouvez utiliser une combinaison de Series.isin()
et 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
Il s’agit essentiellement de l’algorithme que vous avez qualifié de "maladroit", utilisant les méthodes idiomatiques pandas
. Notez les index de lignes en double. Notez également que cela ne vous donnera pas le résultat attendu si df1
et df2
n’a pas d’indices de rangées qui se chevauchent, c’est-à-dire si
In [93]: df1.index & df2.index
Out[93]: Int64Index([], dtype='int64')
En fait, cela ne donnera pas la sortie attendue si leurs index de lignes ne sont pas égaux.
En SQL, ce problème pourrait être résolu par plusieurs méthodes:
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)
ou rejoindre et puis unpivot (possible dans SQL Server)
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
La seconde pourrait être écrite en pandas avec quelque chose comme:
>>> 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