python python-2.7 pandas dataframe intersect

python - Encontrar filas comunes(intersección) en dos dataframes de Pandas



python-2.7 intersect (3)

En SQL, este problema podría ser resuelto por varios métodos:

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)

o join y luego unpivot (posible en el servidor 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

El segundo podría escribirse en pandas con algo como:

>>> 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

Supongamos que tengo dos dataframes de este formato (llámalos df1 y df2 ):

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

Estoy buscando obtener un marco de datos de todas las filas que tienen un user_id común en df1 y df2 . (es decir, si un user_id está en df1 y df2 , incluya las dos filas en el marco de datos de salida)

Puedo pensar en muchas formas de abordar esto, pero todos me parecen torpes. Por ejemplo, podríamos encontrar todos los user_id s únicos en cada dataframe, crear un conjunto de cada uno, encontrar su intersección, filtrar los dos dataframes con el conjunto resultante y concatenar los dos dataframes filtrados.

Quizás ese sea el mejor enfoque, pero sé que Pandas es inteligente. ¿Hay una manera más simple de hacer esto? Miré la merge pero no creo que eso sea lo que necesito.


Si lo entiendo correctamente, puede usar una combinación de Series.isin() y 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

Este es esencialmente el algoritmo que describió como "torpe", utilizando métodos de pandas idiomáticos. Tenga en cuenta los índices de fila duplicados. Además, tenga en cuenta que esto no le dará el resultado esperado si df1 y df2 no tienen índices de filas superpuestas, es decir, si

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

De hecho, no dará el resultado esperado si sus índices de filas no son iguales.


Tengo entendido que esta pregunta se responde mejor en esta publicación .

Pero brevemente, la respuesta a la OP con este método es simplemente:

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

Lo que da s1 con 5 columnas: user_id y las otras dos columnas de cada uno de df1 y df2.