Przetwarzanie Dużych Plików CSV

Przetwarzanie Dużych Plików CSV
lion137
  • Rejestracja: dni
  • Ostatnio: dni
  • Postów: 5023
1

Jest sprawa, sa dwa wielkie pliki CSV i, wedle jakiejś logiki, trzeba brakujące rekordy z jednego pliku uzupełnić drugim, i, uzupełniony plik, zwrócić. Jak to zrobić efektywnie, jest to w Pythonie, ale to bez znaczenia, bo jak coś się znajdzie w czyms innym to się serwis zrobi. Będę inwestygował, nawet se już zdzirę zrobiłem:), ale jak ktoś coś już ma, rozwiązał podobne, to chętnie skorzystam;)

PA
  • Rejestracja: dni
  • Ostatnio: dni
  • Postów: 3889
2

Sprecyzuje co masz na myśli pisząc duże pliki csv

lion137
  • Rejestracja: dni
  • Ostatnio: dni
  • Postów: 5023
0

Tak ~ kilka milionów liniii każdy, nie wiem dokładnie.

Althorion
  • Rejestracja: dni
  • Ostatnio: dni
  • Postów: 1620
3

Kilka milionów linii po kilkaset znaków to jeszcze nie powinien być problem — może i już się nie mieści w cache’u, ale tak prawie. Prawie na pewno wystarczy podejście „na pałę” — wczytać pierwszy plik do setu, wczytać drugi plik do setu, zwrócić pierwszy | drugi, fajrant.

lion137
  • Rejestracja: dni
  • Ostatnio: dni
  • Postów: 5023
0

Masz rację, może tak być, tylko nie wiem czy logika tego uzupełniania pozwoli, zobacze na to jutro.

Spine
  • Rejestracja: dni
  • Ostatnio: dni
  • Postów: 6962
2

Jaką chcesz logikę?
Doklejasz jeden plik do drugiego, sortujesz linie i sprawdzasz je po kolei, czy poprzednia linia == obecna linia. Jeśli tak, to usuwasz obecną.

lion137
  • Rejestracja: dni
  • Ostatnio: dni
  • Postów: 5023
0

Dobra, jednak drugi plik, ten w którym szukamy, (szukanie jest prostsze niż myślałem - odwzorowuje logikę left join) będzie wielki, kilkadziesiąt GB, może i ponad 100.

Spine
  • Rejestracja: dni
  • Ostatnio: dni
  • Postów: 6962
1

ChatGPT radzi, żeby przerzucić te pliki CSV do bazy danych: https://chatgpt.com/share/682da7ad-3c60-800a-848e-4e8c8ade88f9
Wtedy będziesz mógł na tych wielkich plikach wykonywać zapytania.

ŁF
  • Rejestracja: dni
  • Ostatnio: dni
3

Jak wyglądają dane w plikach? Posortowane? Kolejność taka sama w obu? Losowa?
Skąd wiadomo, że jakichś danych brakuje?

Jeśli nie posortowane (przynajmniej w jednym pliku), to prawdopodobnie będziesz musiał to zrobić. Potem 1) jedziesz linijka po linijce po drugim pliku i 2) przepisujesz do pliku docelowego, 3) szukasz binarnie (w plikach tekstowych też da się wyszukiwać binarnie) odpowiadającej linijki w pierwszym, posortowanym pliku, 4) jeśli linijki w drugim pliku brakuje na podstawie pewnych kryteriów, to dopisujesz linijkę do docelowego pliku z pliku pierwszego.
Zresztą narzędzia masz już gotowe i to nawet do nieposortowanych plików - grep, awk, diff itp. (-> https://stackoverflow.com/questions/21188905/how-to-find-which-line-is-missing-in-another-file).

  • Rejestracja: dni
  • Ostatnio: dni
  • Postów: 158
2

ja bym spróbował zrobić unikalny klucz na podstawie wiersza z pierwszego pliku, może da się skrócić na tyle aby klucz zmieścił się w pamięci. Wtedy reszta będzie prosta, przeglądamy pierwszy plik, tworzymy klucz, zapisujemy jako hash (np. dict w Pythonie), przeglądamy drugi i dopisujemy brakujące wiersze. Raczej nie da się szybciej.

Charles_Ray
  • Rejestracja: dni
  • Ostatnio: dni
  • Postów: 1907
1

Może nie musisz ładować całego pliku do pamięci: https://www.baeldung.com/java-read-lines-large-file

lion137
  • Rejestracja: dni
  • Ostatnio: dni
  • Postów: 5023
0

Pewnie że nie muszę, a nawet nie mogę, zatanawiam się nad technologiami, jak polars, dask...

obscurity
  • Rejestracja: dni
  • Ostatnio: dni
1

Ile rekordów jest w tych plikach konkretnie?
Ja bym przejechał pierwszy plik, przepisywał do wyjściowego i dla każdej linii liczył jakiś krótki checksum, długość checksuma w zależności od ilości rekordów 24 do 32 bitów tak żeby cała tablica się zmieściła w pamięci i w pamięci odhaczasz znalezione checksumy w tablicy bitów.
Potem jedziesz po drugim pliku i przepisujesz do wyjściowego pliku wszystkie linie których checksuma nie było wcześniej, a te które były zapamiętujesz
na końcu trzeci przejazd po pierwszym pliku żeby porównać rekordy bezpośrednio z tymi które miały kolizje.

Złożoność obliczeniowa O(n) i optymistycznie pamięciowa O(1)

Brzmi jak minuta roboty z chatgpt + kilkanaście minut działania skryptu.
Nawet nie musisz parsować tych plików jako csv tylko możesz potraktować jak stringi

DA
  • Rejestracja: dni
  • Ostatnio: dni
  • Postów: 149
1
Spine napisał(a):

Jaką chcesz logikę?
Doklejasz jeden plik do drugiego, sortujesz linie i sprawdzasz je po kolei, czy poprzednia linia == obecna linia. Jeśli tak, to usuwasz obecną.

Popieram, można np. tak:

Kopiuj
cat file1 file2 > tmp_file
sort -u tmp_file > result
AD
  • Rejestracja: dni
  • Ostatnio: dni
  • Postów: 342
0

Duckdb zobacz. Wymienione przez ciebie polars, pandas itp też może dać radę.
Jak tak zapytać off top. Co za pojebane..... generuje Csv po 100gb i jak to zrobił.

lion137
  • Rejestracja: dni
  • Ostatnio: dni
  • Postów: 5023
1
ŁF napisał(a):

Jak wyglądają dane w plikach? Posortowane? Kolejność taka sama w obu? Losowa?
Skąd wiadomo, że jakichś danych brakuje?

Jeśli nie posortowane (przynajmniej w jednym pliku), to prawdopodobnie będziesz musiał to zrobić. Potem 1) jedziesz linijka po linijce po drugim pliku i 2) przepisujesz do pliku docelowego, 3) szukasz binarnie (w plikach tekstowych też da się wyszukiwać binarnie) odpowiadającej linijki w pierwszym, posortowanym pliku, 4) jeśli linijki w drugim pliku brakuje na podstawie pewnych kryteriów, to dopisujesz linijkę do docelowego pliku z pliku pierwszego.
Zresztą narzędzia masz już gotowe i to nawet do nieposortowanych plików - grep, awk, diff itp. (-> https://stackoverflow.com/questions/21188905/how-to-find-which-line-is-missing-in-another-file).

Nie są posortowane, tak wiem jakich brakuje bo pewna wartość w pierwszym (niewielkim pliku) jest specyficzna. W sumie to na razie jednak tego nie robię. A problem jest taki, że dla tych specyficznych wartości trzeba znaleźć inną wartość z ogromnego pliku. Wpadłem na pomysł, żeby batchami iterowac po tym wielkim i dodawac do słownika tylko te potrzebne, i chyba big data nie będą potzrebne, ale jak powyżej, na razie muszę to zostawić

ToTomki
  • Rejestracja: dni
  • Ostatnio: dni
  • Postów: 1359
2

To może być potraktowane jako spam, bo to nie odpowiedź na pytanie, ale chciałbym tylko zarzucić taką myśli, że jeśli masz wpływ na to skąd i jakie biorą się te dane, to może warto się zastanowić czy aby na pewno powinny to być .csv, a nie na przykład .parquet, w razie gdybyś musiał regularnie dokonywać tych działań to warto jakoś zrównoleglać operacje np. sparkiem.
Taka tylko wolna myśl, chociaż pewnie to po prostu dwie .csvki i elo ^^, następny task

flinst-one
  • Rejestracja: dni
  • Ostatnio: dni
  • Postów: 348
1
Spine napisał(a):

ChatGPT radzi, żeby przerzucić te pliki CSV do bazy danych: https://chatgpt.com/share/682da7ad-3c60-800a-848e-4e8c8ade88f9
Wtedy będziesz mógł na tych wielkich plikach wykonywać zapytania.

To jest właśnie zawsze moje podejście do tematu. Jak się pojawia jakiś temat przetwarzania plików (np. z innych systemów) to finalnie się okazuje, że to i tak w bazie potem ląduje. IMHO w sql ciężej mdyfikować/uzupełnić brakujące dane, w pythonie to chyba łatwiej się pisze (ale może wolniej działać).

Satanistyczny Awatar
  • Rejestracja: dni
  • Ostatnio: dni
  • Postów: 750
2

Jeśli danych jest masa i nie mieści się w pamięci oraz dane są nieuporządkowane, i to co chcesz wykonać brzmi jak opis działania na tabelach baz danych, to wrzucenie tego do bazy danych wydaje się racjonalne. Jakby nie patrzeć alternatywą jest implementowanie dość typowo bazodanowych elementów. Zaoszczędzony czas możesz poświęcić na czytanie literatury o budowie systemów zarządzania bazami danych. Trochę tego jest. Tak książek jak i publikacji w mniejszych formatach.

SL
  • Rejestracja: dni
  • Ostatnio: dni
  • Postów: 1019
1

Ważne są wymagania wydajnościowe. Jak to ma być zrobione raz/od czasu do czasu to szczerze mówiąc wszystko będzie ok. Python może i będzie 100x wolniejszy niż optymalne rozwiązanie, ale who cares.

Jak lubisz SQL to DuckDB. Jak nie to po prostu poproś czat GPT, żeby napisał to w jakimś wydajnym języku i elo

Jedynym problemem może być użycie pamięci więc warto poprosić czata o rozwiązanie strumieniowe, jeśli tak się da

Nie szedłbym w żadne "smart" rozwiązania, bo ktoś to musi utrzymywać. Duck jest fajny, bo każdy zna SQLa. Zwykły kod jest fajny, bo implementacja szczegółowej logiki jest prostsza niż konfiguracja jakiegoś "smart" rozwiązania

lion137
  • Rejestracja: dni
  • Ostatnio: dni
  • Postów: 5023
0

Dzięki, yhm, DuckDB, spoko, może niedługo do tego wrócę, to zobaczę.

FA
  • Rejestracja: dni
  • Ostatnio: dni
  • Lokalizacja: warszawa
  • Postów: 315
0

Nie są posortowane, tak wiem jakich brakuje bo pewna wartość w pierwszym (niewielkim pliku) jest specyficzna. W sumie to na razie jednak tego nie robię. A problem jest taki, że dla tych specyficznych wartości trzeba znaleźć inną wartość z ogromnego pliku. Wpadłem na pomysł, żeby batchami iterowac po tym wielkim i dodawac do słownika tylko te potrzebne, i chyba big data nie będą potzrebne, ale jak powyżej, na razie muszę to zostawić

Jak jeden plik jest malutki to mozesz załadowac go sobie całego do pamieci, i tak jak mówisz wczytywac "linia po linii" ten wielki plik. To powinno byc optymalne rozwiazanie, O(n) i najwiekszy wąskim gardłem bedzie odpowiednio sprawne wczytywanie duze pliku

Zarejestruj się i dołącz do największej społeczności programistów w Polsce.

Otrzymaj wsparcie, dziel się wiedzą i rozwijaj swoje umiejętności z najlepszymi.