Dask (fsspec) 从多个 zip 文件中读取并连接同名的 csv 文件
我有多个压缩文件,每个压缩文件里都有一些同名的csv文件,比如:
- foo1.zip 里有 a.csv、b.csv、c.csv
- foo2.zip 里有 a.csv、b.csv、c.csv
- foo3.zip 里有 a.csv、b.csv、c.csv 等等。
我想从每个压缩文件中读取特定名称的csv文件,并把它们合并在一起。也就是说,所有的 a 文件要合并在一起,所有的 b 文件也要合并,依此类推。(a、b、c 文件最后会一起合并——我使用 Dask,因为最终的文件太大,无法放进内存里。)
我试过使用这个链接里的方法这里,但我把文件名的通配符换成了压缩文件的通配符:
dfa = dd.read_csv('zip://a.csv::foo*.zip' ,delimiter=";", header=0,index_col=False)
result = dfa.compute()
print(result)
但是这样只加载了第一个压缩文件里的 a.csv 文件。我也试过:
dfa = dd.read_csv("foo*.zip::a.csv",delimiter=";", header=0,index_col=False)
但这样似乎读取了所有的 csv 文件,不管它们的名字是什么。
有人能告诉我我哪里出错了吗?谢谢!
我希望 dfa = dd.read_csv('zip://a.csv::foo*.zip' ,delimiter=";", header=0,index_col=False)
能打开并合并所有匹配 foo*.zip 的 'a.csv' 文件。
结果:只返回了第一个 a.csv 文件。
1 个回答
0
fsspec 只支持在最里面的文件系统上进行 glob 操作(在这个例子中是 ZIP 文件内部),而不是在多个可能的文件系统上进行。
而且,调用 read_csv 一次只会产生一个文件系统,所以你提供的两个路径实际上都是在同一个 ZIP 文件的上下文中被理解的,正如你所注意到的。这是早期 dask 设计时做出的一个决定,目的是为了能够根据一个正在使用的文件系统来划分任务。
要完成这个任务,你需要手动操作:
dfs = [dd.read_csv(fn, ...) for fn in ("zip://a.csv::foo1.zip", "zip://a.csv::fo2.zip")]
ddf = dd.concat(dfs)
result = ddf.compute()