Estoy trabajando con un archivo csv grande y la penúltima columna tiene una cadena de texto que quiero dividir por un delimitador específico. Me preguntaba si hay una manera simple de hacer esto usando pandas o python.
CustNum CustomerName ItemQty Item Seatblocks ItemExt
32363 McCartney, Paul 3 F04 2:218:10:4,6 60
31316 Lennon, John 25 F01 1:13:36:1,12 1:13:37:1,13 300
Quiero dividir por el espacio (' ')
y luego los dos puntos (':')
en la Seatblocks
columna, pero cada celda daría como resultado un número diferente de columnas. Tengo una función para reorganizar las columnas para que la Seatblocks
columna esté al final de la hoja, pero no estoy seguro de qué hacer a partir de ahí. Puedo hacerlo en Excel con la text-to-columns
función integrada y una macro rápida, pero mi conjunto de datos tiene demasiados registros para que Excel los maneje.
En última instancia, quiero tomar registros como los de John Lennon y crear varias líneas, con la información de cada conjunto de asientos en una línea separada.
Respuestas:
Esto divide los bloques de asiento por espacio y le da a cada uno su propia fila.
O, para dar a cada cadena separada por dos puntos en su propia columna:
Esto es un poco feo, pero tal vez alguien intervenga con una solución más bonita.
fuente
DataFrame
muy rápidamente. En mi caso, ejecutar el código en una tabla de ~ 200M resultó en el uso de ~ 10G de memoria (+ intercambio ...).split()
, porque simplementereduce()
atravesar la columna funciona de maravilla. El problema puede estar enstack()
...NameError: name 'Series' is not defined
para esto. de donde seSeries
supone que debe venir? EDITAR: no importa, debería serpandas.Series
ya que se refiere al artículo depandas
from pandas import Series
por conveniencia / brevedad.A diferencia de Dan, considero que su respuesta es bastante elegante ... pero desafortunadamente también es muy ineficiente. Entonces, dado que la pregunta menciona "un gran archivo csv" , permítame sugerirle que intente en un shell la solución de Dan:
... comparado con esta alternativa:
... y esto:
El segundo simplemente se abstiene de asignar la Serie 100 000, y esto es suficiente para hacerlo alrededor de 10 veces más rápido. Pero la tercera solución, que irónicamente desperdicia muchas llamadas a str.split () (se llama una vez por columna por fila, por lo que es tres veces más que para las otras dos soluciones), es aproximadamente 40 veces más rápida que la primera, porque incluso evita tener una instancia de las 100 000 listas. Y sí, ciertamente es un poco feo ...
EDITAR: esta respuesta sugiere cómo usar "to_list ()" y evitar la necesidad de una lambda. El resultado es algo como
que es incluso más eficiente que la tercera solución, y ciertamente mucho más elegante.
EDITAR: el aún más simple
también funciona y es casi tan eficiente.
EDITAR: aún más simple ! Y maneja NaNs (pero menos eficiente):
fuente
tolist()
es perfecta. En mi caso, solo quería una de las piezas de datos en la lista y pude agregar directamente una sola columna a mi df existente usando .ix:df['newCol'] = pd.DataFrame(df.col.str.split().tolist()).ix[:,2]
obect of type 'float' has no len()
que era desconcertante, hasta que me di cuenta de que algunas de mis filas teníanNaN
en ellas, en lugar de hacerlostr
.Otra solución similar con el encadenamiento es el uso
reset_index
yrename
:Si en la columna NO hay
NaN
valores, la solución más rápida es usar lalist
comprensión con elDataFrame
constructor:Pero si la columna contiene
NaN
solo funcionastr.split
con el parámetroexpand=True
que devuelveDataFrame
( documentación ), y explica por qué es más lento:fuente
expand=True
opción de trabajarpandas.DataFrames
mientras se usa,.str.split()
por ejemplo.Otro enfoque sería así:
fuente
También puede usar groupby () sin necesidad de unirse y apilar ().
Utilice los datos de ejemplo anteriores:
fuente
0 31316 Lennon, John 25 F01 300 1:13:36:1,12 A
y la siguiente línea0 31316 Lennon, John 25 F01 300 1:13:37:1,13 B
Este parece un método mucho más fácil que los sugeridos en otras partes de este hilo.
dividir filas en el marco de datos de pandas
fuente