Python高效地将多个文件合并为单个csv文件

时间:2019-05-26 00:41:31

标签: python pandas csv

我有一组文件,想将它们合并到一个CSV文件(一个矩阵)中。 e,有一些问题。

  • 文件不是CSV文件
  • 文件没有相同的列
  • 我不知道这些列
  • 文件很多(超过100,000个)

每个文件中都有应该在矩阵中获得值1的列的名称。 示例:

#File Alpha
dog
house
car

#File Beta
dog
cat

#resulting matrix
,dog,house,car,cat
Alpha,1,1,1,0
Beta,1,0,0,1

经过研究,我提出了以下构想:

import pandas
import os
import shutil

df = pandas.DataFrame()
df['dir'] = 0

directory_0 = os.fsencode("direc0")

for file in os.listdir(directory_0):
    filename = os.fsdecode(file)
    df.append(pandas.Series( name = filename))
    with open("direc10{}".format(filename), "r") as f:
        for line in f:
            if len(line[:-1]) > 0:
                if line[:-1] in df.columns:
                    df.loc[filename, line[:-1]] = 1
                else:
                    df[line[:-1]] = 0
                    df.loc[filename, line[:-1]] = 1
df.fillna(0, inplace=True)
df.to_csv("dataset.csv")

一些评论

  • 有两个目录。 “目录”列用于目录编号(0或1)。我剪切了第二个目录的代码,因为它是相同的(只是该目录有另一个数字)
  • line [:-1]因为有一个我不想要的“ \ n”

问题 这段代码可以完成工作,但是需要很长的时间。

#Runtime for the above code
500 files after 17 seconds
1,000 files after 50 seconds
1,500 files after 111 seconds
2,000 files after 203 seconds
2,500 files after 324 seconds
3,000 files after 489 seconds
3,500 files after 695 seconds
4,000 files after 960 seconds

有没有一种方法可以更快地执行此操作(几个小时内可以存储100,000个文件)?

预先感谢:)

PS:请原谅我的英语,这不是我的母语

1 个答案:

答案 0 :(得分:0)

100.000行不是用CSV文件轻松处理的大小-您会失去很多-在SQL数据库中保留此数据结构会更加有效。

此外,使Pandas搜索列名是线性的使效率降低的原因是,当您输入数千个单词时,为每个文件行运行的if line[:-1] in df.columns将开始承担重担。 / p>

另外,对于约100000个文件,甚至os.listdir可能也很慢-pathlib.Path.iterdir可能更快。

无论如何,将其构建为Python字典,该字典具有O(1)的时间来获取键,将会更快。您可以稍后将其放入数据框中,或者在确实需要时将信息直接记录在CSV文件中。

import pathlib

dir1 = pathlib.Path("direc0")  # Pathlib will also take care of filesystem filename encodings

data = {}

for filepath in dir1.iterdir():
    for line in filepath.open():
        line = line.strip()
        data.setdefault(line, set()).add(filepath.name)

此时,您已将所有数据存储在内存中,其中单词作为键,而一组包含每个单词作为值的文件名。

要直接编写CSV文件,此代码就足够了-因为 所有数据都在内存中,并且代码避免了线性搜索,这应该足够快。问题在于数据是否首先不能容纳在内存中。

import csv
from collections import defaultdict

transposed = {}
for key, values in data.items():
    for value in values:
        transposed.set_default(value, set()).add(key)


with open("dataset.csv", "wt") as file:
    writer = csv.writer(file)
    headers = list(data.keys())

    writer.writerow(["file",] + headers)
    for key, values in transposed.items():
        writer.writerow([key,] + [int(word in values) for word in headers ])