gpt4 book ai didi

python - 从多个数据源创建 DataFrame 时,我们应该使用 for 循环还是列表理解?

转载 作者:太空宇宙 更新时间:2023-11-03 12:53:25 28 4
gpt4 key购买 nike

这个问题与@jpp:s 在Merging files with similar name convention to a dataframe 中的回答相关以及将较早的线程 (Put csv-files in separate dataframes depending on filename) 标记为重复的决定,因为该线程中的三个答案要么不起作用 (2/3) 要么很差 (1/3)。

忽略无效的答案,据说一个答案(我的答案)质量很差,因为 "using concat within a for loop is explicitly not recommended by the docs" .


被诟病的方法:

dataframes = {}
for filename in filenames:
_df = pd.read_csv(filename)
key = filename[:3]
try:
dataframes[key] = pd.concat([dataframes[key], _df], ignore_index=True)
except KeyError:
dataframes[key] = _df

可接受的方法(dd 是一个字典,其中每个值都是一个文件名列表,每个键是每个文件名的前三个字符):

dict_of_dfs
for k, v in dd.items():
dict_of_dfs[k] = pd.concat([pd.read_csv(fn) for fn in v], ignore_index=True)

现在我同意 concat 调用(接受的方法)中的列表理解比调用 concat 的 for 循环更有效在每个 DataFrame 上。

但这是否意味着我们应该始终通过在 concat 调用(或 append) 并且使用 for 循环是如此以至于它实际上是错误?那么可读性呢?我个人(当然)认为我批评的方法更具可读性。


如果我们在 DataFrame.append 上阅读 pandas 文档我们了解到 for 循环或列表理解都不是“生成 DataFrame 的推荐方法”:

The following, while not recommended methods for generating DataFrames, show two ways to generate a DataFrame from multiple data sources.

Less efficient:

>>> df = pd.DataFrame(columns=['A'])
>>> for i in range(5):
... df = df.append({'A': i}, ignore_index=True)
>>> df

A
0 0
1 1
2 2
3 3
4 4

More efficient:

>>> pd.concat([pd.DataFrame([i], columns=['A']) for i in range(5)],
... ignore_index=True)

A
0 0
1 1
2 2
3 3
4 4

所以。我的问题如下:

  1. 在多个数据源上循环并使用 concat 来创建 DataFrame 的一个或多个实例,所以这是错误的

  2. 在这种情况下,我们是否应该始终使用列表理解?

  3. 文档似乎不建议既不使用列表理解也不使用 for 循环,那么推荐从多个创建 DataFrame(s) 的方法是什么数据来源?


非常感谢@piRSquared 和@jpp 的回答。我仍然不相信将 for 循环中的 concat 分类为 错误 的地步,而列表理解是 < strong>正确并接受

给定以下测试数据:

df = pd.DataFrame({'A': np.arange(0, 25000), 'B': np.arange(0, 25000)})

for i in range(0, 50):
df.to_csv('{}.csv'.format(i))

方法:

def conc_inside_loop(filenames):
df = None
for filename in filenames:

if df is None:
df = pd.read_csv(filename)
continue

df = pd.concat([df, pd.read_csv(filename)], ignore_index=True)

return df

def conc_list_comprehension(filenames):
return pd.concat([pd.read_csv(filename) for filename in filenames], ignore_index=True)

时间:

>> %timeit -n 10 conc_inside_loop(glob.glob('*.csv'))
460 ms ± 15.4 ms per loop (mean ± std. dev. of 7 runs, 10 loops each)


>> %timeit -n 10 conc_list_comprehension(glob.glob('*.csv'))
363 ms ± 32.9 ms per loop (mean ± std. dev. of 7 runs, 10 loops each)

显然列表理解效率更高(我已经说过我理解)。但差异并不大。 我认为您不能将一种方法差到错误的地步,而另一种方法正确,因为我们在这里看到了差异。

如@piRSquared 所述,最后一个问题过于宽泛。但是第三种方法是在 for 循环之外使用 concat:

def conc_outside_loop(filenames):

df_list = []
for filename in filenames:
df_list.append(pd.read_csv(filename))

return pd.concat(df_list, ignore_index=True)

>> %timeit -n 10 conc_outside_loop(glob.glob('*.csv'))
344 ms ± 23.4 ms per loop (mean ± std. dev. of 7 runs, 10 loops each)

最佳答案

  1. Is looping and using concat on multiple data sources to create one or multiple instance(s) of DataFrame so poor that it is wrong?

是的! Pandas 很棒。但是你应该不惜一切代价避免不必要的 Pandas 对象的生产。创建 Pandas 对象可能很昂贵,DataFrames 比 Series 更昂贵,但这可能是所有 python 的True。对于“批评”方法:在一个循环中,您创建一个 Pandas 对象,该对象将在循环的下一次迭代中被覆盖。您应该考虑如何收集数据,以便在收集结束时生成 Pandas 对象。

  1. Should we always use list comprehension in a case like this?

不!正如我上面所说,将其视为为构建 Pandas 对象准备的收集数据。理解只是这样一种收集方式。

  1. The docs don't seem to recommend using neither list comprehension or for loop, so what is the recommended way of creating DataFrame(s) from multiple data sources?

这太宽泛了。许多方法都可以作为案例。只是不要在循环中使用 concatappend 。我几乎每次都会说错。

我所说的“每次”实际上并不是“每次”的意思。我的意思是,您永远不应该在循环之前的某个时间点创建一个数据帧,然后循环,并且在每次迭代中都要经历将某些内容附加到先前初始化的数据帧的麻烦。每次迭代都变得非常昂贵。在“已接受”答案的情况下:它将一个数据帧分配给一个字典键,然后单独留下。它不会反复被弄乱。

关于python - 从多个数据源创建 DataFrame 时,我们应该使用 for 循环还是列表理解?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/53156489/

28 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com