读取文件夹中的多个镶木地板文件,然后使用python

时间:2018-08-05 17:27:09

标签: pandas csv parquet

我是python的新手,我有一个场景,其中存在多个拼写文件,文件名顺序排列。例如:一个文件夹中的par_file1,par_file2,par_file3等,最多100个文件。

我需要按顺序读取从file1开始的镶木地板文件,并将其写入单个csv文件。写入file1的内容后,应将file2的内容附加到没有标题的同一csv。请注意,所有文件都具有相同的列名,并且只有数据被拆分为多个文件。

我学会了使用pyarrow通过以下代码将单个实木复合地板转换为csv文件

将熊猫作为pd导入

df = pd.read_parquet('par_file.parquet')

df.to_csv('csv_file.csv')

但是我无法将其扩展为多个镶木文件循环并附加到单个csv。 熊猫有没有办法做到这一点?或任何其他方式可以提供很大帮助。谢谢。

5 个答案:

答案 0 :(得分:6)

我遇到了这个问题,看熊猫是否可以本地读取分区的镶木地板数据集。我不得不说,当前的答案是不必要的冗长(使其难以解析)。我还认为,不断打开/关闭文件句柄然后根据大小扫描到它们的末尾并不是特别有效。

更好的选择是将所有实木复合地板文件读入单个DataFrame中,并写入一次:

from pathlib import Path
import pandas as pd

data_dir = Path('dir/to/parquet/files')
full_df = pd.concat(
    pd.read_parquet(parquet_file)
    for parquet_file in data_dir.glob('*.parquet')
)
full_df.to_csv('csv_file.csv')

或者,如果您真的只想追加到文件:

data_dir = Path('dir/to/parquet/files')
for i, parquet_path in enumerate(data_dir.glob('*.parquet')):
    df = pd.read_parquet(parquet_path)
    write_header = i == 0 # write header only on the 0th file
    write_mode = 'w' if i == 0 else 'a' # 'write' mode for 0th file, 'append' otherwise
    df.to_csv('csv_file.csv', mode=write_mode, header=write_header)

最后一个替代方案是在开始时附加以"a+"模式打开目标CSV文件的每个文件,并在每次写入/追加时保持文件句柄扫描到文件末尾(我相信这是可行的,但是尚未实际上对其进行了测试):

data_dir = Path('dir/to/parquet/files')
with open('csv_file.csv', "a+") as csv_handle:
    for i, parquet_path in enumerate(data_dir.glob('*.parquet')):
        df = pd.read_parquet(parquet_path)
        write_header = i == 0 # write header only on the 0th file
        df.to_csv(csv_handle, header=write_header)

答案 1 :(得分:3)

这帮助我将所有实木复合地板文件加载到一个数据帧中

import glob
 files = glob.glob("*.snappy.parquet")
 data = [pd.read_parquet(f,engine='fastparquet') for f in files]
 merged_data = pd.concat(data,ignore_index=True)

答案 2 :(得分:0)

如果要将文件复制到本地计算机上并运行代码,则可以执行以下操作。下面的代码假定您在与实木复合地板文件相同的目录中运行代码。它还假定文件的命名与您在上面提供的名称相同:“订单。例如:par_file1,par_file2,par_file3,依此类推,一个文件夹中最多包含100个文件。”如果您需要搜索文件,则需要使用glob获取文件名,并显式提供要保存csv的路径:open(r'this\is\your\path\to\csv_file.csv', 'a')希望对您有所帮助。

import pandas as pd

# Create an empty csv file and write the first parquet file with headers
with open('csv_file.csv','w') as csv_file:
    print('Reading par_file1.parquet')
    df = pd.read_parquet('par_file1.parquet')
    df.to_csv(csv_file, index=False)
    print('par_file1.parquet appended to csv_file.csv\n')
    csv_file.close()

# create your file names and append to an empty list to look for in the current directory
files = []
for i in range(2,101):
    files.append(f'par_file{i}.parquet')

# open files and append to csv_file.csv
for f in files:
    print(f'Reading {f}')
    df = pd.read_parquet(f)
    with open('csv_file.csv','a') as file:
        df.to_csv(file, header=False, index=False)
        print(f'{f} appended to csv_file.csv\n')

您可以根据需要删除打印语句。

使用python 3.6pandas 0.23.3中进行了测试

答案 3 :(得分:0)

对于那些尝试读取远程文件的人来说是一个小小的改变,这有助于更快地读取它(对远程文件来说,直接read_parquet对我而言这样做的速度要慢得多):

export function f(key: string): { key: string } { // <- return type
  return { key };
}

interface WithKey {
  key: string;
  ignoreMe?: string;
}

const result: WithKey = f('myKey');

result.key; // works
result.ignoreMe // works (undefined)

不过会增加一点临时内存开销。

答案 4 :(得分:0)

我有类似的需求,我读到当前的 Pandas 版本支持将目录路径作为 read_csv 函数的参数。所以你可以像这样读取多个镶木地板文件:

import pandas as pd    
df = pd.read_parquet('path/to/the/parquet/files/directory')    

它将所有内容连接到单个数据帧中,以便您可以立即将其转换为 csv:

df.to_csv('csv_file.csv')

确保您根据文档具有以下依赖项:

  • pyarrow
  • fastparquet