Tengo un marco de datos de pandas que tomo de una base de datos, por lo que no tengo mucho control sobre el formato. Por razones que desafían la explicación, en algunos casos, la consulta devuelve True / False, en otros, devuelve 1 / NULL. Esto entra en un csv, que luego se lee en el marco de datos.

Si la columna es Verdadero / Falso, se leen correctamente y puedo decir:

DF = DF[DF['column']]

Para obtener solo las filas donde la columna tiene True. Es genial.

Sin embargo, cuando los datos son 1 / Nulo, el 1 es una cadena, por lo que todo se complica.

Me gustaría hacer:

DF = DF[ DF['column'] or DF['column'] == '1']

Sin embargo, eso no funciona.

Alternativamente, si hubiera una manera de verificar fácilmente si tengo '1' / '' y, de ser así, convertir la columna a Verdadero / Falso, eso también funcionaría.

2
Brian Postow 9 may. 2016 a las 22:51

3 respuestas

La mejor respuesta

No es fácil, porque el número 1 es igual True. Entonces, primero convierto los valores a string y luego verifico la cadena 1 por str.contains:

DF = pd.DataFrame({'column':[True, True, 1,  1, 1]})
print DF

  column
0   True
1   True
2      1
3      1
4      1

print DF[DF['column'].astype(str).str.contains('1')]

  column
2      1
3      1
4      1

O use la antigua solución Ayhan:

print  DF[DF['column'].astype(str) == '1' ]

  column
2      1
3      1
4      1

Editar:

Si necesita marcar True o el número 1:

DF = pd.DataFrame({'column':[True, True, 1,  1, 1, False, 2]})
print DF
  column
0   True
1   True
2      1
3      1
4      1
5  False
6      2

print DF[DF['column'] == 1]
  column
0   True
1   True
2      1
3      1
4      1

print DF[DF['column'] == True]
  column
0   True
1   True
2      1
3      1
4      1

Funciona, porque True es igual 1 en comparación.

1
jezrael 9 may. 2016 a las 20:34

Estabas cerca, solo encierra cada regla entre paréntesis y usa | para el lógico OR.

In [1]: DF = pd.DataFrame({'column':[True, True, 1,  '1', 1, False, 2]})

In [2]: DF[(DF['column'] == True) | (DF['column'] == 1)]
Out[2]:
  column
0   True
1   True
2      1
4      1

Puedes agregar una tercera regla de la misma manera

In [3]: DF[(DF['column'] == True) | (DF['column'] == 1) | (DF['column'] == '1')]
Out[3]:
  column
0   True
1   True
2      1
3      1
4      1
0
masat 10 may. 2016 a las 17:22

Si está sacando de una base de datos donde sabe que tendrá estas situaciones, ¿por qué no simplemente reemplazar una manta?

In [70]:  df = pd.DataFrame(data={'a': ['hello',True,''], "b": 

[1,'bar',None]}, index=['row1','row2', 'row3'])

In [71]:  df.replace(to_replace={1:True,'1':True,'':False,None:False})
Out[71]:
          a      b
row1  hello   True
row2   True    bar
row3  False  False

In [72]: df
Out[72]:
          a     b
row1  hello     1
row2   True   bar
row3         None

In [73]:

Con este enfoque, puede tener un diccionario de asignación limpio de valores que le gustaría reemplazar.

Esto también se puede hacer a nivel de columna, si solo hay columnas específicas se usaría en:

In [6]: df.a.replace({np.bool(1):True, np.bool(0):False, 1:True,'1':True,'':False,None:False}, inplace=True)

In [7]: df
Out[7]:
               a      b
row1       hello      1
row2        True    bar
row3       False   None
npboolrow   True  False
0
Kelvin 9 may. 2016 a las 20:45