seleccionar recorrer nombre for filtrar filas fila eliminar datos columnas columna cambiar borrar python pandas dataframe

python - recorrer - los pandas obtienen filas que NO están en otro marco de datos



recorrer filas pandas (11)

Aquí hay otra forma de resolver esto:

df1[~df1.index.isin(df1.merge(df2, how=''inner'', on=[''col1'', ''col2'']).index)]

O:

df1.loc[df1.index.difference(df1.merge(df2, how=''inner'', on=[''col1'', ''col2'']).index)]

Tengo dos marcos de datos de pandas que tienen algunas filas en común.

Supongamos que dataframe2 es un subconjunto de dataframe1.

¿Cómo puedo obtener las filas de dataframe1 que no están en dataframe2?

df1 = pandas.DataFrame(data = {''col1'' : [1, 2, 3, 4, 5], ''col2'' : [10, 11, 12, 13, 14]}) df2 = pandas.DataFrame(data = {''col1'' : [1, 2, 3], ''col2'' : [10, 11, 12]})


Como ya se insinuó, isin requiere que las columnas y los índices sean los mismos para una coincidencia. Si la coincidencia solo debe estar en el contenido de la fila, una forma de obtener la máscara para filtrar las filas presentes es convertir las filas en un Índice (Multi):

In [77]: df1 = pandas.DataFrame(data = {''col1'' : [1, 2, 3, 4, 5, 3], ''col2'' : [10, 11, 12, 13, 14, 10]}) In [78]: df2 = pandas.DataFrame(data = {''col1'' : [1, 3, 4], ''col2'' : [10, 12, 13]}) In [79]: df1.loc[~df1.set_index(list(df1.columns)).index.isin(df2.set_index(list(df2.columns)).index)] Out[79]: col1 col2 1 2 11 4 5 14 5 3 10

Si se debe tener en cuenta el índice, set_index tiene un argumento de palabra clave anexar para agregar columnas al índice existente. Si las columnas no se alinean, la lista (df.columns) se puede reemplazar con especificaciones de columna para alinear los datos.

pandas.MultiIndex.from_tuples(df<N>.to_records(index = False).tolist())

alternativamente podría usarse para crear los índices, aunque dudo que esto sea más eficiente.


La solución actualmente seleccionada produce resultados incorrectos. Para resolver correctamente este problema, podemos realizar una unión izquierda de df1 a df2 , asegurándonos primero de obtener solo las filas únicas para df2 .

Primero, necesitamos modificar el DataFrame original para agregar la fila con datos [3, 10].

df1 = pd.DataFrame(data = {''col1'' : [1, 2, 3, 4, 5, 3], ''col2'' : [10, 11, 12, 13, 14, 10]}) df2 = pd.DataFrame(data = {''col1'' : [1, 2, 3], ''col2'' : [10, 11, 12]}) df1 col1 col2 0 1 10 1 2 11 2 3 12 3 4 13 4 5 14 5 3 10 df2 col1 col2 0 1 10 1 2 11 2 3 12

Realice una unión izquierda, eliminando duplicados en df2 para que cada fila de df1 una con exactamente 1 fila de df2 . Use el indicator parámetro para devolver una columna adicional que indique de qué tabla era la fila.

df_all = df1.merge(df2.drop_duplicates(), on=[''col1'',''col2''], how=''left'', indicator=True) df_all col1 col2 _merge 0 1 10 both 1 2 11 both 2 3 12 both 3 4 13 left_only 4 5 14 left_only 5 3 10 left_only

Crear una condición booleana:

df_all[''_merge''] == ''left_only'' 0 False 1 False 2 False 3 True 4 True 5 True Name: _merge, dtype: bool

¿Por qué otras soluciones están mal?

Algunas soluciones cometen el mismo error: solo verifican que cada valor sea independiente en cada columna, no juntos en la misma fila. Agregar la última fila, que es única pero tiene los valores de ambas columnas de df2 expone el error:

common = df1.merge(df2,on=[''col1'',''col2'']) (~df1.col1.isin(common.col1))&(~df1.col2.isin(common.col2)) 0 False 1 False 2 False 3 True 4 True 5 False dtype: bool

Esta solución obtiene el mismo resultado incorrecto:

df1.isin(df2.to_dict(''l'')).all(1)


Mi forma de hacerlo implica agregar una nueva columna que sea única para un marco de datos y usar esto para elegir si se debe mantener una entrada

df2[col3] = 1 df1 = pd.merge(df_1, df_2, on=[''field_x'', ''field_y''], how = ''outer'') df1[''Empt''].fillna(0, inplace=True)

Esto hace que cada entrada en df1 tenga un código: 0 si es exclusivo de df1, 1 si está en ambos dataFrames. Luego usa esto para restringir a lo que quieres

answer = nonuni[nonuni[''Empt''] == 0]


Qué tal esto:

df1 = pandas.DataFrame(data = {''col1'' : [1, 2, 3, 4, 5], ''col2'' : [10, 11, 12, 13, 14]}) df2 = pandas.DataFrame(data = {''col1'' : [1, 2, 3], ''col2'' : [10, 11, 12]}) records_df2 = set([tuple(row) for row in df2.values]) in_df2_mask = np.array([tuple(row) in records_df2 for row in df1.values]) result = df1[~in_df2_mask]


Supongamos que tiene dos marcos de datos, df_1 y df_2 con múltiples campos (nombres de columna) y desea encontrar las únicas entradas en df_1 que no están en df_2 en función de algunos campos (por ejemplo, fields_x, fields_y), siga los siguientes pasos.

Paso 1.Agregue una columna key1 y key2 a df_1 y df_2 respectivamente.

Paso 2. Combina los marcos de datos como se muestra a continuación. field_x y field_y son nuestras columnas deseadas.

Paso 3. Seleccione solo aquellas filas de df_1 donde key1 no es igual a key2.

Paso4.Drop key1 y key2.

Este método resolverá su problema y funciona rápido incluso con grandes conjuntos de datos. Lo he probado para marcos de datos con más de 1,000,000 de filas.

df_1[''key1''] = 1 df_2[''key2''] = 1 df_1 = pd.merge(df_1, df_2, on=[''field_x'', ''field_y''], how = ''left'') df_1 = df_1[~(df_1.key2 == df_1.key1)] df_1 = df_1.drop([''key1'',''key2''], axis=1)


Suponiendo que los índices son consistentes en los marcos de datos (sin tener en cuenta los valores reales de col):

df1[~df1.index.isin(df2.index)]


También puede concat df1 , df2 :

x = pd.concat([df1, df2])

y luego elimine todos los duplicados:

y = x.drop_duplicates(keep=False, inplace=False)


Un método sería almacenar el resultado de una combinación interna de ambos dfs, luego podemos simplemente seleccionar las filas cuando los valores de una columna no son tan comunes:

In [119]: common = df1.merge(df2,on=[''col1'',''col2'']) print(common) df1[(~df1.col1.isin(common.col1))&(~df1.col2.isin(common.col2))] col1 col2 0 1 10 1 2 11 2 3 12 Out[119]: col1 col2 3 4 13 4 5 14

EDITAR

Otro método que ha encontrado es usar isin que producirá filas de NaN que puede soltar:

In [138]: df1[~df1.isin(df2)].dropna() Out[138]: col1 col2 3 4 13 4 5 14

Sin embargo, si df2 no ​​inicia filas de la misma manera, esto no funcionará:

df2 = pd.DataFrame(data = {''col1'' : [2, 3,4], ''col2'' : [11, 12,13]})

producirá todo el df:

In [140]: df1[~df1.isin(df2)].dropna() Out[140]: col1 col2 0 1 10 1 2 11 2 3 12 3 4 13 4 5 14


puedes hacerlo usando el método isin(dict) :

In [74]: df1[~df1.isin(df2.to_dict(''l'')).all(1)] Out[74]: col1 col2 3 4 13 4 5 14

Explicación:

In [75]: df2.to_dict(''l'') Out[75]: {''col1'': [1, 2, 3], ''col2'': [10, 11, 12]} In [76]: df1.isin(df2.to_dict(''l'')) Out[76]: col1 col2 0 True True 1 True True 2 True True 3 False False 4 False False In [77]: df1.isin(df2.to_dict(''l'')).all(1) Out[77]: 0 True 1 True 2 True 3 False 4 False dtype: bool