Количество вхождений для объектов в столбце списков для действительно большого файла CSV - PullRequest
0 голосов
/ 17 января 2020

У меня есть огромный CSV-файл (8 ГБ), содержащий несколько столбцов. Один из столбцов представляет собой столбец списков, который выглядит следующим образом:

     YEAR              WIN_COUNTRY_ISO3
200  2017         ['BEL', 'FRA', 'ESP']
201  2017                ['BEL', 'LTU']
202  2017                ['POL', 'BEL']
203  2017                       ['BEL']
204  2017  ['GRC', 'DEU', 'FRA', 'LVA']
205  2017                       ['LUX']
206  2017         ['BEL', 'SWE', 'LUX']
207  2017                       ['BEL']
208  2017                            []
209  2017                            []
210  2017                            []
211  2017                       ['BEL']
212  2017                       ['SWE']
213  2017                ['LUX', 'LUX']
214  2018                ['DEU', 'LUX']
215  2018                ['ESP', 'PRT']
216  2018                       ['AUT']
217  2018                ['DEU', 'BEL']
218  2009                       ['ESP']
219  2009                       ['BGR']

Каждый из трехбуквенного кода представляет страну. Я хотел бы создать таблицу частот для каждой страны, чтобы я мог подсчитать вхождения каждой страны во всем столбце. Поскольку файл действительно большой, и мой P C не может обработать загрузку всего CSV-файла как кадра данных, я стараюсь лениво прочитать файл и перебрать строку -> получить последний столбец и добавить объект в каждую строку столбца WIN_COUNTRY_ISO3 (который является последним столбцом) для набора словарей.

import sys
from itertools import islice
n=100
i = 0
col_dict={}
with open(r"filepath.csv") as file:
    for nline in iter(lambda: tuple(islice(file, n)), ()):
        row = nline.splitline
        WIN_COUNTRY_ISO3 = row[-1]
        for iso3 in WIN_COUNTRY_ISO3:
            if iso3 in col_dict.keys():
                col_dict[iso3]+=1
            else:
                col_dict[iso3]=1
        i+=1
        sys.stdout.write("\rDoing thing %i" % i)
        sys.stdout.flush()
    print(col_dict)

Однако этот процесс занимает очень много времени. Я попытался выполнить итерацию нескольких строк, используя код

for nline in iter(lambda: tuple(islice(file, n)), ())

Q1:

Однако, похоже, это не работает, и python обрабатывает файл один за другим. Кто-нибудь знает наиболее эффективный способ для меня для подсчета каждой страны для действительно большого файла, как мой?

Получившаяся таблица будет выглядеть следующим образом:

Country     Freq
BEL         4543
FRA         4291
ESP         3992
LTU         3769
POL         3720
GRC         3213
DEU         3119
LVA         2992
LUX         2859
SWE         2802
PRT         2584
AUT         2374
BGR         1978
RUS         1770
TUR         1684

Я также хотел бы создать таблицу частот по каждому году (в столбце ГОД), если кто-нибудь сможет мне помочь с этим. Спасибо.

Ответы [ 2 ]

0 голосов
/ 17 января 2020

Если вы можете обрабатывать awk, вот один:

$ cat program.awk
{
    while(match($0,/'[A-Z]{3}'/)) {
        a[substr($0,RSTART+1,RLENGTH-2)]++
        $0=substr($0,RSTART+RLENGTH)
    }
}
END {
    for(i in a)
        print a[i],i
}

Выполните его:

$ awk -f program.awk file

Вывод:

1 AUT
3 DEU
3 ESP
1 BGR
1 LTU
2 FRA
1 PRT
5 LUX
8 BEL
1 POL
1 GRC
1 LVA
2 SWE

$0 обрабатывает все запись (строка) данных, поэтому она может включать в себя ложные попадания из другого места в записи. Вы можете улучшить это с помощью правильного разделения поля, но так как оно не было доступно, я не могу больше помочь. См. Gnu awk, FS и, возможно, FPAT в Google.

0 голосов
/ 17 января 2020

Попробуйте это:

from collections import defaultdict
import csv
import re

result = defaultdict(int)
f = open(r"filepath.csv")
next(f)
for row in f:
    data = re.sub(r'[\s\d\'\[\]]', '', row)
    if data:
        for x in data.split(','):
            result[x] += 1
print(result)
...