Pracuję z dużym plikiem csv, a obok ostatniej kolumny znajduje się ciąg tekstu, który chcę podzielić za pomocą określonego separatora. Zastanawiałem się, czy można to zrobić w prosty sposób za pomocą pand lub Pythona?
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
Chcę podzielić przez spację, (' ')
a następnie dwukropek (':')
w Seatblocks
kolumnie, ale każda komórka spowodowałaby inną liczbę kolumn. Mam funkcję zmiany kolejności kolumn, aby Seatblocks
kolumna znajdowała się na końcu arkusza, ale nie jestem pewien, co dalej robić. Mogę to zrobić w programie Excel z wbudowaną text-to-columns
funkcją i szybkim makrem, ale mój zbiór danych ma zbyt wiele rekordów, aby program Excel mógł je obsłużyć.
Ostatecznie chcę wziąć rekordy Johna Lennona i utworzyć wiele linii, z informacjami z każdego zestawu miejsc w osobnej linii.
Odpowiedzi:
Spowoduje to podzielenie bloków siedzenia według przestrzeni i nadanie każdemu osobnego rzędu.
Lub, aby umieścić każdy ciąg rozdzielany dwukropkami w osobnej kolumnie:
To trochę brzydkie, ale może ktoś wpadnie na ładniejsze rozwiązanie.
źródło
DataFrame
bardzo szybko powiększa rozmiar . W moim przypadku uruchomienie kodu na ~ 200M tabeli spowodowało użycie pamięci ~ 10G (+ zamiana ...).split()
, bo zwykłereduce()
przechodzenie przez kolumnę działa jak urok. Problem może wtedy leżeć wstack()
...NameError: name 'Series' is not defined
z tego powodu. skądSeries
ma pochodzić? EDYCJA: nieważne, powinno być,pandas.Series
ponieważ odnosi się do pozycji zpandas
from pandas import Series
dla wygody / zwięzłości.W odróżnieniu od Dana uważam jego odpowiedź za dość elegancką ... ale niestety jest też bardzo, bardzo nieefektywna. Tak więc, ponieważ pytanie dotyczyło „dużego pliku csv” , zasugeruję wypróbowanie rozwiązania powłoki Dana:
... w porównaniu z tą alternatywą:
... i to:
Drugi po prostu powstrzymuje się od przydzielenia 100 000 serii, a to wystarczy, aby zrobić to około 10 razy szybciej. Ale trzecie rozwiązanie, które nieco ironicznie marnuje wiele wywołań funkcji str.split () (jest wywoływane raz na kolumnę w wierszu, czyli trzy razy więcej niż w przypadku pozostałych dwóch rozwiązań), jest około 40 razy szybsze niż pierwsze, ponieważ unika nawet umieszczania 100 000 list. I tak, z pewnością jest trochę brzydki ...
EDYCJA: ta odpowiedź sugeruje, jak używać "to_list ()" i uniknąć potrzeby stosowania lambdy. Wynik jest podobny
które jest jeszcze wydajniejsze niż trzecie rozwiązanie, a na pewno dużo bardziej eleganckie.
EDYCJA: jeszcze prostsza
działa też i jest prawie tak samo wydajny.
EDYCJA: jeszcze prostsza ! I obsługuje NaN (ale mniej wydajne):
źródło
tolist()
jest doskonała. W moim przypadku chciałem tylko jeden z fragmentów danych na liście i mogłem bezpośrednio dodać pojedynczą kolumnę do mojego istniejącego df, używając .ix:df['newCol'] = pd.DataFrame(df.col.str.split().tolist()).ix[:,2]
obect of type 'float' has no len()
co było zaskakujące, dopóki nie zdałem sobie sprawy, że niektóre z moich awantur mająNaN
w nich w przeciwieństwie dostr
.Innym podobnym rozwiązaniem w przypadku łączenia jest użycie
reset_index
irename
:Jeśli w kolumnie NIE są
NaN
wartości, najszybszym rozwiązaniem jest użycielist
zrozumienia zDataFrame
konstruktorem:Ale jeśli kolumna zawiera
NaN
działa tylkostr.split
z parametrem,expand=True
który zwracaDataFrame
( dokumentacja ), i wyjaśnia, dlaczego jest wolniejsza:źródło
expand=True
pracy z opcjipandas.DataFrames
podczas korzystania.str.split()
np.Inne podejście byłoby takie:
źródło
Może również używać funkcji groupby () bez konieczności łączenia się i stosu ().
Użyj powyższych przykładowych danych:
źródło
0 31316 Lennon, John 25 F01 300 1:13:36:1,12 A
i następna linia0 31316 Lennon, John 25 F01 300 1:13:37:1,13 B
Wydaje się, że jest to znacznie łatwiejsza metoda niż te sugerowane w innym miejscu w tym wątku.
podziel wiersze w ramce danych pandy
źródło