我有一个很大的CSV文件,其中包含一些字符串类型的列(dtype object
)和其他类型的int64
列。
字符串列和整数列在CSV中都可以为空。整数列中的空值表示零,而空字符串应保持为空字符串。
我想聚合所有其他列上的所有整数列。 最好的方法是什么?
输出最终应该是一个聚合的单个CSV文件。 该文件可能无法整体放入内存,这就是为什么我尝试使用Dask的原因,但是我很难理解如何执行此操作。
这是适用于内存的小型CSV的有效熊猫代码:
import pandas as pd
df = pd.read_csv("input_file.csv", na_filter=False)
df[metrics_to_aggregate] = df[metrics_to_aggregate].fillna(0).apply(pd.to_numeric)
df = df.groupby(dimensions_to_aggregate, as_index=False).sum()
df.to_csv("output_file.csv", index=False)
例如,输入df
可能类似于:
dimension1 dimension2 dimension3 metric1 metric2 metric3
0 foo bar 1 1
1 foo bar 2 2
2 foo bar 1 4 2
3 foo bar foobar 2 1
输出df
应为:
dimension1 dimension2 dimension3 metric1 metric2 metric3
0 foo bar 1 4 2
1 foo bar 3 1 2
2 foo bar foobar NaN 2 1
位置:
metrics_to_aggregate=['metric1', 'metric2', 'metric3']
dimensions_to_aggregate=['dimension1', 'dimension2', 'dimension3']
答案 0 :(得分:1)
如果文件未排序,则不使用大量内存就很难处理:您需要为文件中出现的每个键(维值列表)保持运行中的聚合。这样做可能是个好方法,但这取决于细节,例如存在多少可能性。可能可以分块进行处理,然后一起处理这些分块,但是您仍然需要足够的内存来存储所有当前聚集的键值。
一个简单且相当通用的解决方案是首先进行排序。 Unix sort
命令将愉快地对太大而无法放入内存的文件进行排序。然后,可以轻松地对已排序的文件进行分块处理。这是显示原理的序列:您可能需要更改一些细节:
首先,我稍微扩展了文件以显示正在发生的情况,并删除了标题行(sort
将被视为数据):
input_file.csv:
foo bar 1 1
a a 9 9 9
z z 8 8 8
a a 9 9 9
foo bar 2 2
foo bar 1 4 2
foo bar foobar 2 1
z z 7 7 7
a a 9 9 9
然后我使用了命令:
sort input_file.csv -o input_file_sorted.csv --key=1,3
这给了我
input_file_sorted.csv
a a 9 9 9
a a 9 9 9
a a 9 9 9
foo bar 1 4 2
foo bar 1 1
foo bar 2 2
foo bar foobar 2 1
z z 7 7 7
z z 8 8 8
然后我运行了这个Python程序:
import csv
number_of_dims = 3
number_of_aggs = 3
def aggregate(agg, data):
for i,d in enumerate(data):
if d != "":
agg[i] += int(d)
return
with open("input_file_sorted.csv", newline="") as f1:
with open("output_file,csv", "w", newline="") as f2:
csv_reader = csv.reader(f1, delimiter='\t')
csv_writer = csv.writer(f2, delimiter='\t')
key = None
agg = [0] * number_of_aggs
for l in csv_reader:
new_key = l[:number_of_dims]
if key is None:
key = new_key
if key != new_key:
csv_writer.writerow(key + agg)
agg = [0] * number_of_aggs
key = new_key
aggregate(agg, l[number_of_dims:])
csv_writer.writerow(key + agg)
那吸引了我:
output_file.csv:
a a 27 27 27
foo bar 1 4 2
foo bar 3 1 2
foo bar foobar 0 2 1
z z 15 15 15
希望有帮助!