如何向 map(pd_read_csv) 添加其他参数?
Posted
技术标签:
【中文标题】如何向 map(pd_read_csv) 添加其他参数?【英文标题】:How to add additional arguments to map(pd_read_csv)? 【发布时间】:2020-08-03 10:46:25 【问题描述】:大约 2 年前,有人用一种非常优雅的方式将多个 csv 文件读入一个数据帧: Import multiple csv files into pandas and concatenate into one DataFrame
filepaths = [f for f in listdir("./data") if f.endswith('.csv')]
df = pd.concat(map(pd.read_csv, filepaths))
但是,如果您想要一个不同的分隔符或者您的 csv 文件没有标题怎么办?您在上面的语句中将 header = None 之类的参数放在哪里?
【问题讨论】:
您可以使用functools.partial
或将read_csv
包装在一个lambda 函数中,例如lambda x: pd.read_csv(x, header=None)
。也值得了解map
的作用
列表理解也有效:df = pd.concat([pd.read_csv(f, header=None) for f in filepaths])
@Yo_Chris 好的,但我在某处读到使用列表对内存使用有很大影响。这是真的还是我弄错了?
@SBurggraaff 列表可能会对内存产生很大影响,但情况并非总是如此,尤其是列表理解:***.com/questions/1247486/list-comprehension-vs-map。此外,我刚刚计算了 map
和 6000 个 csv 文件的列表理解之间的差异,而列表理解实际上更快。列表理解:16 s ± 532 ms per loop (mean ± std. dev. of 7 runs, 1 loop each)
地图:16.2 s ± 329 ms per loop (mean ± std. dev. of 7 runs, 1 loop each)
@Yo_Chris 好的,再次感谢您提供的所有信息。它又回到了使用列表。我查找了一些我从找到的示例中编写的两年前的代码。原来我正在将数据框添加到列表中,然后在 pd.concat 函数中使用该列表。事后看来,当您的数据框变得非常大时,这看起来很愚蠢。顺便说一下,列表推导式看起来非常干净整洁。
【参考方案1】:
您可以使用 itertools.starmap。
这个函数需要:
一个函数作为第一个参数, 并在每组参数上运行它来自可迭代(第二 参数 - 元组列表)。我运行了以下示例:
import itertools as it
# read_csv wrapper
def rd_csv(fn, separ, hdr):
print(f'File: fn / sep: separ / header: hdr')
if hdr is None:
return pd.read_csv(fn, sep=separ,
names=['ind', 'POLL_X', 'POLL_Y', 'POLL_Z', 'POLL_DNW', 'AVal', 'ZVal'])
else:
return pd.read_csv(fn, sep=separ, header=hdr)
# Parameters for consecutive calls (filename, separator, header)
inputs = [ ('Input_1.csv', ',', 0), ('Input_2.csv', ';', None) ]
# Read all files
res = pd.concat(it.starmap(rd_csv, inputs), ignore_index=True)
执行期间的测试打印输出为:
File: Input_1.csv / sep: , / header: 0
File: Input_2.csv / sep: ; / header: None
(将它们放到目标版本中)。
注意当header == None时的“特殊处理”。
原因是:
使用 header=0 读取的数据帧将具有从 第一行。 使用 header=None 读取的数据帧将列名设置为 连续的数字,这样连接这些列将无法正确连接。
考虑一下,当header == None时,包装函数 必须自己指定列名(names 参数)(因此它必须包括 硬编码的列名)。
这种组合背后的基本原理是,如果所有这些源文件 要连接到一个 DataFrame 中,它们应该有一个共同的集合 列名,即使某些输入文件实际上不包含它们 在第一行。
【讨论】:
好的,但这有点违背了最初的观点:两行干净的代码。如果你开始使用包装器,你最终会得到更多的代码。 Map 是一个优雅的解决方案,但这里有更多参数。另一个重要的细节是 header=None 列名称以整数形式给出,因此生成的 DataFrame 不能与一起传递的各个列连接。为了规避这个细节,包装器必须自己传递列名列表。也许其他人会想出更好的解决方案。 好的,但是使用地图功能不是没有意义吗?回到使用列表不是更好吗?只是,我以为我在某处读到使用列表连接数据帧会占用大量内存。所以我想知道如何避免这份清单。以上是关于如何向 map(pd_read_csv) 添加其他参数?的主要内容,如果未能解决你的问题,请参考以下文章
如何向 google_map_location_picker 添加语言环境支持? (扑)