Mam około 750 plików (.csv), a każda linia ma jeden wpis, który jest identyfikatorem UUID. Moim celem dla tego skryptu jest policzenie, ile unikalnych identyfikatorów UUID istnieje we wszystkich około 750 plikach. Struktura nazwy pliku wygląda następująco:

DATA-20200401-005abf4e3f864dcb83bd9030e63c6da6.csv

Jak widać, ma datę i losowy identyfikator. Wszystkie znajdują się w tym samym katalogu i wszystkie mają to samo rozszerzenie pliku. Format każdego pliku jest rozdzielany nowymi wierszami i ma po prostu identyfikator UUID, który wygląda następująco: b0d6e1e9-1b32-48d5-b962-671664484616

Próbowałem scalić wszystkie pliki, ale sytuacja się pogmatwała i jest to około 15 GB danych.

Moim ostatecznym celem jest uzyskanie takiego wyniku, który określa liczbę unikalnych identyfikatorów we wszystkich plikach. Na przykład:

Plik1:

xxx-yyy-zzz
aaa-bbb-ccc
xxx-yyy-zzz

Plik2:

xxx-yyy-zzz
aaa-bbb-ccc
xxx-yyy-zzz

Ostateczny wynik po zeskanowaniu tych dwóch plików będzie wyglądał następująco:

The total number of unique ids is: 2

0
Ryan 2 kwiecień 2020, 03:46

5 odpowiedzi

Najlepsza odpowiedź

Jeśli nie musisz używać Pythona, prostym rozwiązaniem może być wiersz poleceń:

cat *.csv | sort -u | wc -l   

Powoduje to przekierowanie zawartości całego pliku CSV do sort -u, które sortuje i usuwa duplikaty, a następnie przekierowuje je do wc -l, które oblicza liczbę wierszy.

Uwaga: sort rozleje się na dysk w razie potrzeby, a jeśli chcesz, możesz kontrolować jego wykorzystanie pamięci za pomocą -S size.

Kusiło mnie, aby uruchomić to na potężnej maszynie z dużą ilością pamięci RAM.

1
jarmod 3 kwiecień 2020, 01:16

Myślę, że najszybszym sposobem na zrobienie tego może być Counter to:

from collections import Counter

with open(filename) as f:
    c = Counter(f)
    print(sum(c.values()))

Licznik podaje liczbę każdego unikalnego przedmiotu. Jest to realizowane za pomocą tablicy haszującej, więc powinno być dość szybkie w przypadku dużej liczby elementów.

2
Jack Casey 2 kwiecień 2020, 05:26

Przeczytaj wszystkie pliki i na bieżąco dodaj wszystkie identyfikatory UUID do zestawu. Zestawy wymuszają unikalność, więc długość zestawu to liczba znalezionych unikalnych identyfikatorów UUID. W przybliżeniu:

import csv
import os

uuids = set()
for path in os.listdir():
    with open(path) as file:
        for row in csv.reader(file):
            uuids.update(row)
print(f"The total number of unique ids is: {len(uuids)}")

Zakłada się, że można przechowywać w pamięci wszystkie unikalne identyfikatory UUID. Jeśli nie możesz, zbudowanie bazy danych na dysku byłoby następną rzeczą do wypróbowania (np. Zamień set na bazę danych sqlite lub coś podobnego). Jeśli masz wiele unikalnych identyfikatorów, które są zbyt duże, aby przechowywać je gdziekolwiek , nadal istnieją rozwiązania, o ile chcesz poświęcić trochę precyzji: https://en.wikipedia.org/wiki/HyperLogLog

-1
Samwise 2 kwiecień 2020, 01:05

Łączenie wszystkich plików csv w katalogu zostało rozwiązane w całkiem popularny post Jedyna różnica polega na tym, że usuwasz duplikaty. Oczywiście działałoby to dobrze tylko wtedy, gdy w każdym pliku jest znaczna liczba duplikatów (przynajmniej wystarczająca, aby wszystkie zdeduplikowane ramki zmieściły się w pamięci i wykonały ostateczne drop_duplicates).

W tym linku są również inne sugestie, takie jak całkowite pominięcie listy.

import glob
import pandas as pd

files = glob.glob('./data_path/*.csv')

li = []

for file in files:
    df = pd.read_csv(file, index_col=None, header=None)
    li.append(df.drop_duplicates())

output = pd.concat(li, axis=0, ignore_index=True)
output = output.drop_duplicates()
0
Chris 2 kwiecień 2020, 00:57

Może coś takiego by zadziałało:

from os import listdir
import re
import pandas as pd

my_folder_path = "C:\\\\"

# Generic regular expression
pat = r"DATA-\d{8}-.+\.csv}"
p = re.compile(pat)

# UUID column in each file (I don't know if this is the case; Adjust accodingly.
uuid_column = "uuids"

# Empty result dataframe with single column
result_df = pd.DataFrame(columns=["unique_uuid"])

file_list = [rf"{my_folder_path}\{i}" for i in listdir(my_folder_path)]
for f in file_list:
    # Check for matching regular expression pattern
    if p.search(f):

        # Read file if pattern matches.
        df = pd.read_csv(f, usecols=[uuid_column])

        # Append only unique values from the new Series to the dataframe
        (result_df["unique_uuid"]
        .append(list(set(df[uuid_column].values)
        .difference(result_df["unique_uuid"].values)))
        )
1
Mark Moretto 2 kwiecień 2020, 01:02