对非常大的 CSV 文件的列表列中的对象进行计数
Count Occurrences for Objects in a Column of Lists for Really Large CSV File
我有一个包含多列的巨大 CSV 文件 (8gb)。其中一列是一列列表,如下所示:
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']
每个三字代码代表一个国家。我想为每个国家/地区创建一个频率 table,这样我就可以计算每个国家/地区在整个列中的出现次数。由于文件非常大,我的 PC 无法处理将整个 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 一个一个地处理文件。有没有人知道最多
对于像我这样的非常大的文件,我生成每个国家/地区计数的有效方法?
结果 table 看起来像这样:
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
如果有人可以帮助我,我还想在每年(在 YEAR 列中)创建频率 table。谢谢。
试试这个:
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)
如果你能处理 awk,这里有一个:
$ cat program.awk
{
while(match([=10=],/'[A-Z]{3}'/)) {
a[substr([=10=],RSTART+1,RLENGTH-2)]++
[=10=]=substr([=10=],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
[=13=]
处理整个数据记录(行),因此它可能包括来自记录中其他地方的错误命中。您可以通过适当的字段分隔来增强它,但由于它不可用,我无能为力。参见 gnu awk,FS
和 google 中的 FPAT
。
我有一个包含多列的巨大 CSV 文件 (8gb)。其中一列是一列列表,如下所示:
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']
每个三字代码代表一个国家。我想为每个国家/地区创建一个频率 table,这样我就可以计算每个国家/地区在整个列中的出现次数。由于文件非常大,我的 PC 无法处理将整个 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 一个一个地处理文件。有没有人知道最多 对于像我这样的非常大的文件,我生成每个国家/地区计数的有效方法?
结果 table 看起来像这样:
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
如果有人可以帮助我,我还想在每年(在 YEAR 列中)创建频率 table。谢谢。
试试这个:
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)
如果你能处理 awk,这里有一个:
$ cat program.awk
{
while(match([=10=],/'[A-Z]{3}'/)) {
a[substr([=10=],RSTART+1,RLENGTH-2)]++
[=10=]=substr([=10=],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
[=13=]
处理整个数据记录(行),因此它可能包括来自记录中其他地方的错误命中。您可以通过适当的字段分隔来增强它,但由于它不可用,我无能为力。参见 gnu awk,FS
和 google 中的 FPAT
。