【问题标题】:Python, loops with changeable parts of filenamesPython,带有可变文件名部分的循环
【发布时间】:2020-05-29 12:23:42
【问题描述】:

我有一堆非常相似的命令,看起来都像这样(df 表示熊猫数据框):

df1_part1=...
df1_part2=...
...
df1_part5=...
df2_part1=...

我想给它做个循环,如下:

for i in range(1,5):
for j in range(1,5):
df%i_part%j=...

当然,它不适用于 %。但我想必须有一些简单的方法来做到这一点。 你能帮帮我吗?

【问题讨论】:

  • 将数据框分配给字典而不是分配给变量。

标签: python pandas dataframe


【解决方案1】:

您可以尝试以下选项之一:

  1. 创建一个映射您的 df 的字典并通过数据框的名称访问它:
mapping = {"df1_part1": df1_part1, "df1_part2": df1_part2}
for i in range(1,5):
    for j in range(1,5):
        mapping[f"df{i}_part{j}"] = ...
  1. 使用globals 动态访问您的变量:
df1_part1=...
df1_part2=...
...
df1_part5=...
df2_part1=...

for i in range(1,5):
    for j in range(1,5):
        globals()[f"df{i}_part{j}"] = ...

【讨论】:

  • 在不必要的时候避免使用全局变量,stackoverflow.com/questions/17874946/…
  • 在我的情况下,全局变量的替代方法是什么?我无法定义文件列表,它会很长。我不仅在左侧有带有数字的文件,在右侧还有更多。
  • 我还是觉得没有简单的解决方案很奇怪。在 SAS 中,写 df%i_part%j=... 就足够了,一切都很好。宏变量使之成为可能。
  • 有一个简单的解决方案:使用像字典这样的适当数据结构,而不是用globals 挖掘变量名的内部结构。
  • 我有 verb_kd_top3_z =top3[top3.kd.isin(top3_zl_kd)==True] 之类的命令,我不想手动创建所有文件的列表或字典。
【解决方案2】:

一种方法是在列表列表中收集您的 pandas 数据帧并迭代该列表,而不是尝试动态解析您的 python 代码。

df1_part1=...
df1_part2=...
...
df1_part5=...
df2_part1=...

dflist = [[df1_part1, df1_part2, df1_part3, df1_part4, df1_part5],
          [df2_part1, df2_part2, df2_part3, df2_part4, df2_part5]]
for df in dflist:
    for df_part in df:
        # do something with df_part

【讨论】:

  • 这个解决方案没有多大帮助。实际上,我在每个命令中有很多地方,其中相同的数字是某个文件的一部分。列表的列表会很长。
【解决方案3】:

假设此过程是数据准备的一部分,我想提一下,您应该尽可能尝试使用“数据准备管道”。否则,几个月后代码将变得一团糟。

有几种方法可以解决这个问题。

字典是处理这个问题的最直接的方法。

df_parts = {
            'df1' : {'part1': df1_part1, 'part2': df1_part2,...,'partN': df1_partN},
            'df2' : {'part1': df1_part1, 'part2': df1_part2,...,'partN': df2_partN},
            '...' : {'part1': ..._part1, 'part2': ..._part2,...,'partN': ..._partN},
            'dfN' : {'part1': dfN_part1, 'part2': dfN_part2,...,'partN': dfN_partN},
           }

# print parts from `dfN`
for val in for df_parts['dfN'].values():
    print(val)

# print part1 for all dfs
for df in df_parts.values():
    print(df['part1'])

# print everything
for df in df_parts:
    for val in df_parts[df].values():
        print(val)

这种方法的好处是您可以遍历整个字典,但您不包括range,这可能会在以后造成混淆。此外,最好将每个 df_part 直接分配给 dict,而不是分配可能使用一次或两次的 N*N 变量。在这种情况下,您可以只使用 1 个变量 并在进行时重新分配它:

# code using df1_partN
df1 = df_parts['df1']['partN']
# stuff to do
# happy? checkpoint
df_parts['df1']['partN'] = df1

【讨论】:

  • 代码很多,所以最后我没有节省任何时间。问题是我有 5 种不同类型的文件名,其中包含数字,而不仅仅是 df...所以我需要 5 个字典,然后我必须重写所有命令。手动复制、粘贴和更改数字更容易。我可以更快地做到这一点。
  • 我同意问题出在“糟糕”的数据准备上,但这样做不是我的主意。而且我仍然必须使用它,我无权更改名称约定。
猜你喜欢
  • 2022-10-02
  • 1970-01-01
  • 2021-04-08
  • 2017-07-11
  • 1970-01-01
  • 2012-07-10
  • 1970-01-01
  • 2019-02-02
  • 1970-01-01
相关资源
最近更新 更多