Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/python/293.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Python 在数千个表中合并行的可扩展方式_Python_Csv_Pandas_Union - Fatal编程技术网

Python 在数千个表中合并行的可扩展方式

Python 在数千个表中合并行的可扩展方式,python,csv,pandas,union,Python,Csv,Pandas,Union,我有大约50k个类似csv的文件,每个文件之间用空格隔开,每个文件大约有几千万行。第一列总是不带空格的字符串,第二列总是正整数,并且没有丢失的数据。在这个问题上,我只对第一列感兴趣,所以请忽略第二列。下面是两个这样的csv文件的玩具示例 example1.csv f1 x f2 x f5 x f7 x ... f1 x f2 x f3 x f4 x f6 x ... example2.csv f1 x f2 x f5 x f7 x ... f1 x f2 x f3 x f4 x f6 x

我有大约50k个类似csv的文件,每个文件之间用空格隔开,每个文件大约有几千万行。第一列总是不带空格的字符串,第二列总是正整数,并且没有丢失的数据。在这个问题上,我只对第一列感兴趣,所以请忽略第二列。下面是两个这样的csv文件的玩具示例

example1.csv

f1 x
f2 x
f5 x
f7 x
...
f1 x
f2 x
f3 x
f4 x
f6 x
...
example2.csv

f1 x
f2 x
f5 x
f7 x
...
f1 x
f2 x
f3 x
f4 x
f6 x
...
如您所见,两个文件中的要素集有重叠,但不相同。我想做的是合并来自所有50k csv文件的数据,并将其转换为以下形式

file_name    f1 f2 f3 f4 f5 f6 f7 ....
example1.csv 1  1  0  0  1  0  1  ...
example2.csv 1  1  1  1  0  1  0  ...
...
所以基本上是构造一个
文件名
x
特征id
的矩阵,如果
特征id
存在于文件中,则为1,否则为0。这里的解析相对简单,重点是可伸缩性,在未来的项目中,行数可能会达到数十亿。我可以访问最多有一到两TB内存和100个内核的机器。因此,我想内存约束不太重要,但我下面所示的简单实现在玩具示例上效果很好,但对于真正的示例来说速度太慢了,并且在第一个文件中达到310000行时似乎挂起,我不知道为什么。(你知道为什么吗?我的直觉说它可能与defaultdict有关,不确定它是如何实现的,而且使用起来可能会很昂贵。)我希望解决方案能够相当快。解决方案最好是使用Python,但其他语言也可以

import os
import gzip
from collections import defaultdict

import pandas as pd


# collect paths to all csv-like files
with open('file_list.txt') as inf:
    inputs = [_.split() for _ in inf.readlines]

inputs_map = dict(zip(inputs, range(len(inputs))))

res = defaultdict(lambda :[0] * len(inputs))
for k, infile in enumerate(inputs):
    print(k, infile)
    source_file = os.path.abspath(infile)
    source_file_id = inputs_map[source_file]
    # starting parsing the csv-like file
    with gzip.open(source_file, 'rt') as inf:
        for kl, line in enumerate(inf):
            feature_id = line.split()[0]
            res[feature_id][source_file_id] = 1
            if (kl + 1) % 10000 == 0:
                print('File {0}'.format(k), 'Line {0}'.format(kl + 1), source_file)

df = pd.DataFrame(res)
df.index = inputs
print('starting writing to disk...')
df.T.to_csv('output.csv')

对于两个文件,您可以使用
cat example1.csv example2.csv | cut-d”“-f1 | sort-u获取行名
。AFAIK
sort
非常快速高效,如果内存不足,它会使用磁盘。重复将此过程应用于成对的文件可能是一个好方法。您的意思是首先获得所有行的并集,然后循环遍历每个文件吗?我仍然需要哪个文件包含哪个功能的信息。你能使用hdfs+spark吗?就可伸缩性而言,它似乎是很好的工具?如果你有所有的行名称并对输入文件进行排序,那么就很容易编写程序以线性时间和恒定内存生成矩阵。如果你的问题是伸缩性,我想他们会更糟;)关于你的问题有一个很好的页面:你确定这会扩大吗<代码>[在fs中读取f的ex(f)]对我来说很棘手。我不确定,我会尝试一下。首先尝试使用几个文件。它可能无法工作,因为
[read_ex(f)for f in fs]
读取了太多的冗余信息,并会破坏内存。我做了一个粗略的计算,列表理解可能会消耗3TB的内存,需要19个小时。。。如果我想到其他事情,我会更新帖子。