Tengo un marco de datos, df como esta

a  b  c
1  0  2
5  7  8
4  1  3
3  4  6
5  2  5
.......

Ahora quiero reemplazar esos datos con los siguientes rangos

0-3 = 1
4-6 = 2
7-9 = 3

Los valores de columna son inferiores a 10, por lo que el rango está dentro de 0-9.

Quiero reemplazar los valores de trama de datos anteriores con las categorías de rango y la salida debería ser así

a  b  c
1  1  1
2  3  3
2  1  1
1  2  2
2  1  2
.......

Entonces, si algún valor en el df está dentro de 0-3, debe reemplazarse por 1, y si algo dentro de 4-6 lo reemplaza por 2, etc. ¿Cómo puedo hacer esto?

3
asdfkjasdfjk 28 oct. 2017 a las 16:52

3 respuestas

La mejor respuesta

Utilice pd.cut con apply es decir

df.apply(lambda x : pd.cut(x,[-1,3,6,9],labels=[1,2,3]))
   a  b  c
0  1  1  1
1  2  3  3
2  2  1  1
3  1  2  2
4  2  1  2

Una solución basada en no aplicar sugerida por @coldspeed:

pd.DataFrame(pd.cut(df.values.reshape(-1,),[-1,3,6,9],labels=[1,2,3]).codes.reshape(df.shape)+1,columns=df.columns)

O

pd.DataFrame(pd.cut(np.hstack(df.values),[-1,3,6,9],labels=[1,2,3]).codes.reshape(df.shape)+1,columns=df.columns)
6
Bharath 28 oct. 2017 a las 14:50

Puede usar np.digitize

In [5942]: bins = np.array([0, 4, 7, 10])

In [5943]: pd.DataFrame(np.digitize(df, bins), columns=df.columns)
Out[5943]:
   a  b  c
0  1  1  1
1  2  3  3
2  2  1  1
3  1  2  2
4  2  1  2

O como

In [5947]: bins2 = np.array([-1, 3, 6, 9])

In [5948]: pd.DataFrame(np.digitize(df, bins2, right=True), columns=df.columns)
Out[5948]:
   a  b  c
0  1  1  1
1  2  3  3
2  2  1  1
3  1  2  2
4  2  1  2
2
Bharath 28 oct. 2017 a las 14:02

Usando un poco de matemática:

((df - 1) // 3).clip(0) + 1

   a  b  c
0  1  1  1
1  2  3  3
2  2  1  1
3  1  2  2
4  2  1  2

Alternativamente, replace todos los ceros con uno (el único caso de esquina para tratar) y luego dividir.

(df.replace(0, 1) - 1) // 3 + 1

   a  b  c
0  1  1  1
1  2  3  3
2  2  1  1
3  1  2  2
4  2  1  2
4
cs95 28 oct. 2017 a las 14:14