我有一个大约5400万行的数据集,我需要从制表符分隔的文本文件中读取,从宽格式转换为长格式,并写入新的文本文件。数据太大而无法存储在内存中,所以我一直在使用迭代器。我想从宽到长移动三个单独的变量,所以我一直使用其中三个独立的迭代器
import pandas as pd
import itertools as it
filename = "C:/example.txt"
iter_a = pd.read_table(filename, iterator=True, usecols=col_list_1, chunksize=100000)
iter_b = pd.read_table(filename, iterator=True, usecols=col_list_2, chunksize=100000)
iter_c = pd.read_table(filename, iterator=True, usecols=col_list_3, chunksize=100000)
其中所有usecols列表包含公共标识符和其他不同的列。列名基于年份和属性,因此列列表可能如下所示:
col_list_1 = ['Key', 'A90', 'A91', 'A92']
col_list_2 = ['Key', 'B90', 'B91', 'B92']
col_list_3 = ['Key', 'C90', 'C91', 'C92']
我希望将所有列名更改为没有主要字符/字符的年份,并且仅在这些年份融化。
new_colnames = ['Key', '1990', '1991', '1992']
melt_values = ['1990', '1991', '1992']
for achunk, bchunk, cchunk in it.izip(iter_a, iter_b, iter_c):
achunk.columns = new_colnames
bchunk.columns = new_colnames
cchunk.columns = new_colnames
melted_a = pd.melt(achunk, id_vars='Key', value_vars=melt_values, var_name='Year', value_name='A').set_index(['Key', 'Year']).sort_index()
melted_b = pd.melt(bchunk, id_vars='Key', value_vars=melt_values, var_name='Year', value_name='B').set_index(['Key', 'Year']).sort_index()
melted_c = pd.melt(cchunk, id_vars='Key', value_vars=melt_values, var_name='Year', value_name='C').set_index(['Key', 'Year']).sort_index()
join1 = melted_a.join(melted_b, how='outer')
join2 = join1.join(melted_c, how='outer')
join2.dropna(inplace=True, how='all')
join2.to_csv('C:/output_example.txt', sep='\t')
虽然这确实有效,但需要很长时间。我以15秒的速度在100,000行线上进行了一次迭代。假设它线性扩展,我似乎在看2.25小时的运行时间。有什么好方法可以加快速度吗?也许使用numpy数组或多处理?
答案 0 :(得分:2)
pandas
csv解析器真的很快,但你可能会尝试一个纯python解决方案,因为pandas正在做一些你并不真正关心的事情(类型推断和转换,所有连接对齐,索引等)。
这只是一个开始,但这是一个非常简单的从长到宽的例子。你必须测试它,但我猜它可能比你上面做的更快。
In [30]: %%file tmp.csv
...: Key,A90,A91,A92,B90,B91,B92
...: a,1,2,3,4,5,6
...: b,7,8,9,10,11,12
In [32]: with open('tmp.csv') as f, open('out.csv', 'w') as f2:
...: f2.write('Key,Group,Year,Value\n')
...: for i, line in enumerate(f):
...: if i == 0:
...: _, *headers = line.strip().split(',')
...: headers = [(h[0], '19' + h[1:]) for h in headers]
...: else:
...: key, *rest = line.strip().split(',')
...: for (group, year), value in zip(headers, rest):
...: f2.write(','.join([key, group, year, value]) + '\n')
In [33]: print(open('out.csv').read())
Key,Group,Year,Value
a,A,1990,1
a,A,1991,2
a,A,1992,3
a,B,1990,4
a,B,1991,5
a,B,1992,6
b,A,1990,7
b,A,1991,8
b,A,1992,9
b,B,1990,10
b,B,1991,11
b,B,1992,12