Cómo cambiar una columna en Pandas DataFrame

101

Me gustaría cambiar una columna en un Pandas DataFrame, pero no he podido encontrar un método para hacerlo desde la documentación sin volver a escribir todo el DF. Alguien sabe como hacerlo? Marco de datos:

##    x1   x2
##0  206  214
##1  226  234
##2  245  253
##3  265  272
##4  283  291

Salida deseada:

##    x1   x2
##0  206  nan
##1  226  214
##2  245  234
##3  265  253
##4  283  272
##5  nan  291
raíz
fuente
3
esto realmente debería ser una bandera opcional para la función de cambio
KIC

Respuestas:

155
In [18]: a
Out[18]: 
   x1  x2
0   0   5
1   1   6
2   2   7
3   3   8
4   4   9

In [19]: a.x2 = a.x2.shift(1)

In [20]: a
Out[20]: 
   x1  x2
0   0 NaN
1   1   5
2   2   6
3   3   7
4   4   8
eumiro
fuente
8
Falta el resultado ## 5. ¿Existe una manera fácil en pandas de extender el índice cuando se usa shift?
Waylon Walker
@WaylonWalker Eso se llama rodar en numpy:df['x2'] = np.roll(df['x2'], 1)
ayhan
1
¿Alguien se dio cuenta de esto? # 5 aún falta
Kritz
Tengo que cambiar 100 columnas de la misma manera, ¿cómo puedo hacer un bucle for?
Vincent Roye
2
@Johan, ¿intentaste agregar una fila vacía al final antes de cambiarla?
MikeyE
8

Necesitas usar df.shiftaquí.
df.shift(i)desplaza todo el marco de datos por iunidades hacia abajo.

Entonces, para i = 1:

Entrada:

    x1   x2  
0  206  214  
1  226  234  
2  245  253  
3  265  272    
4  283  291

Salida:

    x1   x2
0  Nan  Nan   
1  206  214  
2  226  234  
3  245  253  
4  265  272 

Entonces, ejecute este script para obtener el resultado esperado:

import pandas as pd

df = pd.DataFrame({'x1': ['206', '226', '245',' 265', '283'],
                   'x2': ['214', '234', '253', '272', '291']})

print(df)
df['x2'] = df['x2'].shift(1)
print(df)
Ayush Jain
fuente
3
Bienvenido a stackoverflow. Su respuesta será más útil si proporciona alguna explicación de cómo debe usarse.
Simon.SA
1
nuevamente, ha perdido una fila # 5 que OP claramente quiere
KIC
6

Definamos el marco de datos de su ejemplo por

>>> df = pd.DataFrame([[206, 214], [226, 234], [245, 253], [265, 272], [283, 291]], 
    columns=[1, 2])
>>> df
     1    2
0  206  214
1  226  234
2  245  253
3  265  272
4  283  291

Entonces podrías manipular el índice de la segunda columna por

>>> df[2].index = df[2].index+1

y finalmente volver a combinar las columnas individuales

>>> pd.concat([df[1], df[2]], axis=1)
       1      2
0  206.0    NaN
1  226.0  214.0
2  245.0  234.0
3  265.0  253.0
4  283.0  272.0
5    NaN  291.0

Quizás no sea rápido pero fácil de leer. Considere establecer variables para los nombres de las columnas y el turno real requerido.

Editar: En general, el cambio es posible según df[2].shift(1)lo ya publicado, pero eso cortaría el remanente.

Kay Wittig
fuente
Me pregunto si hay una manera rápida de hacer esto, y usando un índice de fecha, esencialmente desea cambiar sin truncar nuestra serie y, por lo tanto, debe especificar los valores de índice adicionales. para un cambio de uno, diría algo como series.shift (-1, fill = [datetime (<some date>)]). ¿Es posible algo como esto? Lo encontré aquí stackoverflow.com/questions/36042804/…
OldSchool
5

Si no desea perder las columnas que desplaza más allá del final de su marco de datos, simplemente agregue el número requerido primero:

    offset = 5
    DF = DF.append([np.nan for x in range(offset)])
    DF = DF.shift(periods=offset)
    DF = DF.reset_index() #Only works if sequential index
David Ferris
fuente
3

Supongo que las importaciones

import pandas as pd
import numpy as np

Primero agregue una nueva fila NaN, NaN,...al final de DataFrame ( df).

s1 = df.iloc[0]    # copy 1st row to a new Series s1
s1[:] = np.NaN     # set all values to NaN
df2 = df.append(s1, ignore_index=True)  # add s1 to the end of df

Creará un nuevo DF df2. Quizás haya una forma más elegante pero esto funciona.

Ahora puedes cambiarlo:

df2.x2 = df2.x2.shift(1)  # shift what you want
martin-voj
fuente
2

Intentando dar respuesta a un problema personal y similar al tuyo encontré en Pandas Doc lo que creo que respondería a esta pregunta:

DataFrame.shift (períodos = 1, frecuencia = Ninguno, eje = 0) Índice de desplazamiento por el número deseado de períodos con una frecuencia de tiempo opcional

Notas

Si se especifica freq, los valores del índice se desplazan pero los datos no se realinean. Es decir, use freq si desea extender el índice al cambiar y preservar los datos originales.

Espero ayudar a futuras preguntas en este asunto.

Tha_franklin
fuente
0

Así es como lo hago:

df_ext = pd.DataFrame(index=pd.date_range(df.index[-1], periods=8, closed='right'))
df2 = pd.concat([df, df_ext], axis=0, sort=True)
df2["forecast"] = df2["some column"].shift(7)

Básicamente, estoy generando un marco de datos vacío con el índice deseado y luego los concateno juntos. Pero realmente me gustaría ver esto como una característica estándar en los pandas, así que he propuesto una mejora para los pandas.

KIC
fuente