Je travaille avec un gros fichier csv et l'avant-dernière colonne contient une chaîne de texte que je souhaite diviser par un délimiteur spécifique. Je me demandais s'il existe un moyen simple de le faire en utilisant des pandas ou 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
Je veux diviser par l'espace (' ')
, puis les deux points (':')
dans la Seatblocks
colonne, mais chaque cellule entraînerait un nombre différent de colonnes. J'ai une fonction pour réorganiser les colonnes afin que la Seatblocks
colonne soit à la fin de la feuille, mais je ne sais pas quoi faire à partir de là. Je peux le faire dans Excel avec la text-to-columns
fonction intégrée et une macro rapide, mais mon ensemble de données contient trop d'enregistrements pour Excel à gérer.
En fin de compte, je veux prendre des enregistrements tels que ceux de John Lennon et créer plusieurs lignes, avec les informations de chaque ensemble de sièges sur une ligne distincte.
Réponses:
Cela divise les sièges par espace et donne à chacun sa propre rangée.
Ou, pour donner à chaque chaîne séparée par deux-points dans sa propre colonne:
C'est un peu moche, mais peut-être que quelqu'un vous proposera une solution plus jolie.
la source
DataFrame
fichier très rapidement. Dans mon cas, exécuter le code sur une table de ~ 200M a entraîné une utilisation de la mémoire ~ 10G (+ swap ...).split()
, parce que le simple faitreduce()
de passer à travers la colonne fonctionne comme un charme. Le problème peut alors résider dansstack()
...NameError: name 'Series' is not defined
pour cela. d'où estSeries
censé venir? EDIT: tant pis, ça devrait l'êtrepandas.Series
car il fait référence à l'article depandas
from pandas import Series
par commodité / brièveté.Contrairement à Dan, je trouve sa réponse assez élégante ... mais malheureusement elle est aussi très très inefficace. Donc, puisque la question mentionnait "un gros fichier csv" , laissez-moi vous suggérer d'essayer dans un shell la solution de Dan:
... par rapport à cette alternative:
... et ça:
Le second s'abstient simplement d'allouer 100 000 séries, et cela suffit pour le rendre environ 10 fois plus rapide. Mais la troisième solution, qui gaspille quelque peu ironiquement beaucoup d'appels à str.split () (elle est appelée une fois par colonne par ligne, donc trois fois plus que pour les deux autres solutions), est environ 40 fois plus rapide que la première, car cela évite même d'instanceser les 100 000 listes. Et oui, c'est certainement un peu moche ...
EDIT: cette réponse suggère comment utiliser "to_list ()" et éviter d'avoir besoin d'un lambda. Le résultat est quelque chose comme
qui est encore plus efficace que la troisième solution, et certainement beaucoup plus élégante.
EDIT: le plus simple
fonctionne aussi et est presque aussi efficace.
EDIT: encore plus simple ! Et gère les NaN (mais moins efficaces):
la source
tolist()
est parfaite. Dans mon cas, je ne voulais qu'une des données de la liste et j'ai pu ajouter directement une seule colonne à mon df existant en utilisant .ix:df['newCol'] = pd.DataFrame(df.col.str.split().tolist()).ix[:,2]
obect of type 'float' has no len()
qui était déconcertant, jusqu'à ce que je réalise que certaines de mes lignes avaientNaN
en eux, par opposition àstr
.Une autre solution similaire avec le chaînage est l'utilisation
reset_index
etrename
:Si dans la colonne ne sont PAS des
NaN
valeurs, la solution la plus rapide est d'utiliser lalist
compréhension avec leDataFrame
constructeur:Mais si la colonne contient
NaN
ne fonctionnestr.split
qu'avec le paramètreexpand=True
qui retourneDataFrame
( documentation ), et cela explique pourquoi il est plus lent:la source
expand=True
travail d'option avecpandas.DataFrames
tout en utilisant.str.split()
par exemple.Une autre approche serait comme ceci:
la source
Peut également utiliser groupby () sans avoir besoin de rejoindre et stack ().
Utilisez les données d'exemple ci-dessus:
la source
0 31316 Lennon, John 25 F01 300 1:13:36:1,12 A
et ligne suivante0 31316 Lennon, John 25 F01 300 1:13:37:1,13 B
Cela semble une méthode beaucoup plus facile que celles suggérées ailleurs dans ce fil.
diviser les lignes dans le cadre de données pandas
la source