Función de división de pandas en reversa

Tengo un Pandas Dataframe con una columna que se ve así:

Car_Make 0 2017 Abarth 124 Spider ManualConvertible 1 2017 Abarth 124 Spider AutoConvertible 2 2017 Abarth 124 Spider ManualConvertible 3 2017 Abarth 124 Spider AutoConvertible 4 2017 Abarth 595 ManualHatch 5 2017 Abarth 595 AutoHatch 

Tres preguntas:

1 ¿Cómo guardar datos divididos en panda en orden inverso? – Esto resuelve mi problema, pero no sé cómo o por qué funciona. ¿Alguien puede explicarme esto? Odio pegar copias sin entender por qué funciona

 df['Car_Make'].apply(lambda x:pd.Series(x.split()[::-1])) 

2 He intentado replicarlo usando una función definida por el usuario (que puedo usar de nuevo) con lo siguiente, pero no parece funcionar (ninguna ayuda para entender por qué y la forma correcta de convertir la función Lambda en usuario) función definida

 def f(x): df[x] = pd.Series(x.split()[::-1]) return df 

3 ¿Hay una mejor manera de dividir esta columna por el espacio al revés?

He intentado usar Regex, que funciona, pero no en todas las filas, ya que puedes ver las filas 4 y 5 de una forma ligeramente diferente a la anterior.

Cualquier ayuda sería muy apreciada.

Gracias adrian

Aquí hay una oportunidad para sus tres preguntas:

1) ¿Por qué funciona df['Car_Make'].apply(lambda x:pd.Series(x.split()[::-1])) ?

Descomponerlo:

  1. df['Car_Make'] – la columna con los datos que desea operar
  2. .apply() : un método de pandas DataFrame y Series que aplicará una función a cada columna, o cada fila, en un DataFrame, o a cada fila en una Serie.
  3. lambda x: – la función que se aplicará mediante el método .apply() a cada fila de la Serie. x representa el objeto de registro, que en su caso es la cadena que contiene las entradas Car_Make .
  4. pd.Series() : esto convertirá el valor dentro de él en una serie de pandas .
  5. x.split() : como se mencionó en el punto 3, x es su objeto de cadena y split() es un método de cadena que, cuando se pasa sin parámetros, se divide de manera predeterminada una cadena por sus espacios y devuelve cada objeto de división en una lista .
  6. [::-1] : un útil iterador de lista que invierte una lista, como la que devuelve x.split() . La syntax de la iteración de lista es [start_index:end_index:step] . El uso de un paso -1 itera a través de la lista hacia atrás.

Póngalo todo junto, y ese código está iterando a través de cada registro en df['Car_Make'] , dividiéndolos, invirtiendo el orden de los elementos divididos y devolviendo la lista invertida como un objeto de la serie pandas.

2) Replicando eso con una función definida.

Usted está realmente cerca, solo que la función necesita tomar una fila / registro como su argumento y debe llamarse en el método .apply() . Lo que desea hacer es reemplazar la lambda x , no la forma en que se aplica.

Usando lo que tienes hasta ahora:

 def f(x): return pd.Series(x.split()[::-1]) df['Car_Make'].apply(f) 

3) ¿Hay una mejor manera?

Si desea dividir una cadena y luego invertir el orden de los elementos, no, esta es una excelente manera. Si solo quieres dividir una cierta parte de una cadena a partir de la derecha, rsplit() es un buen método.

Es esto lo que estás buscando:

 df.car_make.str.rsplit(' ', 1, expand=True) # returns: 0 1 0 2017 Abarth 124 Spider ManualConvertible 1 2017 Abarth 124 Spider AutoConvertible 2 2017 Abarth 124 Spider ManualConvertible 3 2017 Abarth 124 Spider AutoConvertible 4 2017 Abarth 595 ManualHatch 5 2017 Abarth 595 AutoHatch 

El código que estás pidiendo aquí:

 df['Car_Make'].apply(lambda x:pd.Series(x.split()[::-1])) 

Hay varias cosas que suceden aquí:

1.) Primero, lambda son básicamente funciones improvisadas. En este caso, es una función sin nombre que toma el argumento x , y devuelve pd.Series(x.split()[::-1] . Más sobre x más adelante.

2.) pd.Series(...) como usted sabe, crea un objeto de la serie pandas como sus datos originales.

3.) x.split() está dividiendo la cadena x con espacio como separador por defecto.

4.) El bit [::-1] es una slice . . Al igual que el range() , se necesitan 3 parámetros, [start: end: steps] . En este caso, significa obtener la cadena de principio a fin, pero use -1 como pasos, es decir, a la inversa. Tenga en cuenta que sólo el parámetro end es obligatorio.

5.) La función principal aquí es apply() en su serie df['Car_Make'] , que es esencialmente una lista de cadenas. apply() toma una función (como map() ) y la aplica a la serie df['Car_Make'] . En este caso, está aplicando la lambda, que toma los datos de su serie y la usa como argumento x para la función.

6.) Poner todo de nuevo juntos. La statement es:

  • pasando los datos de la cadena df['Car_Make'] como x al lambda
  • lambda luego procesa el x.split() para dividir los datos de la cadena en una lista.
  • La lista se clasifica en orden inverso según la división [::-1] .
  • pd.Series() ahora convierte la lista en un objeto Series .
  • El objeto Series es luego devuelto por lambda a su función apply() .
  • La función apply() devuelve el objeto Series resultante, que convenientemente, es la cadena ordenada en sentido inverso que deseaba en una serie.

Sin embargo, si lo único que te importa es la última división, realmente no necesitas hacer la división inversa y todo eso. Fácilmente podría haber hecho lo siguiente y habría devuelto el último artículo en la división de inmediato:

data['Car Make'].apply(lambda x: pd.Series({'Car_Make':x.split()[-1]}))

  Car_Make 0 ManualConvertible 1 AutoConvertible 2 ManualConvertible 3 AutoConvertible 4 ManualHatch 5 AutoHatch 

Gracias por hacer esta pregunta, también aprendí algunas cosas sobre los pandas durante esta respuesta.