时间效率高的长转换大熊猫

时间:2016-06-16 20:05:02

标签: python performance pandas numpy bigdata

我有一个大约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数组或多处理?

1 个答案:

答案 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