tablas - pandas python tutorial español pdf
Compare los marcos de datos de Python Pandas para las filas coincidentes (2)
@ Andrew: Creo que encontré una manera de eliminar las filas de un marco de datos que ya están presentes en otro (es decir, para responder mi EDIT) sin usar bucles; avíseme si no está de acuerdo o si mi OP + EDIT no fue clara declara esto:
ESTO FUNCIONA
Las columnas para ambos marcos de datos son siempre las mismas:
A
,
B
,
C
y
D
Con esto en mente, basado en gran medida en el enfoque de Andrew, aquí se explica cómo eliminar las filas de
df2
que también están presentes en
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''])]
La línea 3 hace lo siguiente:
-
Extraiga solo filas de
df2
que no coincidan con las filas dedf1
: -
Para que 2 filas sean diferentes, CUALQUIER columna de una fila debe
necesariamente será diferente que la columna correspondiente en otra fila. -
Aquí, elegí la columna
A
para hacer esta comparación, es
es posible usar cualquiera de los nombres de columna, pero no TODOS
nombres de columna
NOTA: este método es esencialmente el equivalente del SQL
NOT IN()
.
Tengo este DataFrame (
df1
) en Pandas:
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
Me gustaría verificar si alguna fila (todas las columnas) de otro marco de datos (
df2
) está presente en
df1
.
Aquí está
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
Intenté usar
df.lookup
para buscar una fila a la vez.
Lo hice de esta manera:
list1 = df2.ix[0].tolist()
cols = df1.columns.tolist()
print df1.lookup(list1, cols)
pero recibí este mensaje de error:
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''
También probé
.all()
usando:
print (df2 == df1).all(1).any()
pero recibí este mensaje de error:
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
También probé
isin()
así:
print df2.isin(df1)
pero obtuve
False
todas partes, lo cual no es correcto:
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
¿Es posible buscar un conjunto de filas en un DataFrame, comparándolo con las filas de otro marco de datos?
EDITAR: ¿Es posible soltar filas
df2
si esas filas también están presentes en
df1
?
Una posible solución a su problema sería usar merge . Verificar si alguna fila (todas las columnas) de otro marco de datos (df2) está presente en df1 es equivalente a determinar la intersección de los dos marcos de datos. Esto se puede lograr usando la siguiente función:
pd.merge(df1, df2, on=[''A'', ''B'', ''C'', ''D''], how=''inner'')
Por ejemplo, si df1 era
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
y df2 se definió como:
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
La función
pd.merge(df1, df2, on=[''A'', ''B'', ''C'', ''D''], how=''inner'')
produce:
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
Los resultados son todas las filas (todas las columnas) que están en df1 y df2.
También podemos modificar este ejemplo si las columnas no son las mismas en df1 y df2 y solo comparar los valores de fila que son iguales para un subconjunto de las columnas. Si modificamos el ejemplo original:
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
Luego podemos mirar las columnas comunes usando
common_cols = list(set(df1.columns) & set(df2.columns))
entre los dos marcos de datos y luego combinar:
pd.merge(df1, df2, on=common_cols, how=''inner'')
EDITAR: Nueva pregunta (comentarios), habiendo identificado las filas de df2 que también estaban presentes en el primer marco de datos (df1), ¿es posible tomar el resultado de pd.merge () y luego soltar las filas de df2 que están también presente en df1
No conozco una forma sencilla de lograr la tarea de eliminar las filas de df2 que también están presentes en df1. Dicho esto, puedes usar lo siguiente:
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)
Probablemente exista una mejor manera de lograr esa tarea, pero no estoy al tanto de tal método / función.
EDITAR 2: Cómo soltar las filas de df2 que también están presentes en df1 como se muestra en la respuesta @WR.
El método proporcionado
df2[~df2[''A''].isin(df12[''A''])]
no tiene en cuenta todos los tipos de situaciones.
Considere los siguientes marcos de datos:
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
El uso de los DataFrames anteriores con el objetivo de eliminar filas de df2 que también están presentes en df1 daría como resultado lo siguiente:
A B C D
0 1 1 1 1
1 2 2 2 2
Las filas (1, 1, 1, 1) y (2, 2, 2, 2) están en df2 y no en df1.
Desafortunadamente, el uso del método proporcionado (
df2[~df2[''A''].isin(df12[''A''])]
) da como resultado:
A B C D
6 2 2 2 2
Esto ocurre porque el valor de 1 en la columna A se encuentra tanto en el DataFrame de intersección (es decir (1, 0, 2, 3)) como en df2 y, por lo tanto, elimina tanto (1, 0, 2, 3) como (1, 1, 1, 1). Esto no es intencionado ya que la fila (1, 1, 1, 1) no está en df1 y no debe eliminarse.
Creo que lo siguiente proporcionará una solución. Crea una columna ficticia que luego se utiliza para subconjugar el DataFrame a los resultados deseados:
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)