【问题标题】:Assigning and updating variable names based on a list in a loop in python根据python循环中的列表分配和更新变量名
【发布时间】:2017-11-03 04:13:19
【问题描述】:

我正在使用 Pandas 创建一系列数据框,每个数据框都是前一个数据框的聚合版本。 (我有一个必须递归计算的统计数据。)假设我有一系列变量要聚合,保存在名为 aggVars 的字典中。原始数据框df 有嵌套观察:

year area ind occ aggVars
2000 0001 001 001 ...
2000 0001 001 002 ...
2000 0001 002 001 ...
2000 0001 002 002 ...
2000 0002 001 001 ...
2000 0002 001 002 ...
2000 0002 002 001 ...
2000 0002 002 002 ...
2001 0001 001 001 ...
2001 0001 001 002 ...
.
.
.

我想你明白了。观察嵌套在职业中,在行业内,在区域内,在年份内。

我可以用愚蠢的方式做到这一点:

# DUMB CODE BLOCK
df_job = df.groupby(['year', 'area', 'ind', 'occ'], as_index=False)
df_job = df_job.agg(aggVars)
df_work = df_job.groupby(['year', 'area', 'ind'], as_index=False)
df_work = df_work.agg(aggVars)
df_county = df_work.groupby(['year', 'area'], as_index=False)
df_county = df_county.agg(aggVars)
df_year = df_county.groupby(['year'], as_index=False)
df_year = df_year.agg(aggVars)

(我特意为数据框使用了不同的名称,即df_county 而不是df_area,以反映真实数据中的 .groupby() 变量不会如此整齐地映射到层次结构级别。)

我已经测试过了,它工作正常。但这显然是一种愚蠢的做法。这应该是某种循环。 这就是我的麻烦开始的地方。我可以指定一个列表列表:

aggHierarchy = [['job', ['year', 'area', 'ind', 'occ']],
                ['work', ['year', 'area', 'ind']],
                ['county', ['year', 'area']],
                ['year', ['year']]]

然后循环遍历列表,如下所示:

# BROKEN CODE BLOCK
old_df = 'df'
for level in aggHierarchy:
    new_df = 'df_%s' % level[0]
    new_df = old_df.groupby(level[1], as_index=False)
    new_df = new_df.agg(aggVars)
    old_df = new_df

这里的逻辑是根据aggHierarchy 元素的第一个子元素分配新数据框的名称,然后使用第二个子元素对事物进行分组。但是,当然,这是行不通的。我编写的循环基本上尝试使用new_df = 'df_%s' % level[0] 为新数据框分配一个名称,但我实际上所做的只是创建一个字符串。

此外,Stack Overflow 上到处都有人指出使用列表在循环中分配变量名是Considered Harmful。我明白了——我可以看出这是多么笨拙。 “Use a dictionary”,我看到人们在写。但事情是这样的:这些数据帧的聚合必须以一定的顺序发生,(我相信)我不能用字典来指定。我无法掌握如何从将变量名添加到字典中,到在循环中以特定顺序调用它们。

这就是我的问题,希望我已经提供了足够的背景信息来很好地说明:给定上面的 DUMB CODE BLOCK 之类的代码块,我需要根据其确切内容的列表(或字典!)来更新变量名称我可能事先不知道...我怎样才能在那里创建某种循环?

【问题讨论】:

  • collections.OrderedDict 可能适合您的用例。
  • 您是只对 end 结果感兴趣,还是真的需要所有这些中间数据帧来做其他事情?
  • 如果您能提供一个工作的最小示例,包括aggVars 的特定名称和值,将会很有帮助,这样就可以看到确切的输入和输出。另外,您需要什么输出 - 您需要所有中间数据帧,还是只需要最后一个(例如您的示例中的 df_year)?
  • 我确实需要中间数据帧。我意识到我可以将大部分dumb code block 折叠成两半,即df_year = df_county.groupby(['year'], as_index=False).agg(aggVars)
  • 一个最小的工作示例可能包含我要聚合的三个变量,例如 whiteblackworkers。这些保持计数。然后aggVars = {'white': 'sum', 'black': 'sum', 'workers': 'sum'}。然后,每个聚合数据框将保存折叠在分组变量上的总和。 (在这种情况下,您可以从原始数据构建所有中间数据帧,但这不适用于更复杂的统计数据。)

标签: python pandas


【解决方案1】:

继续使用您的列表,但使用 DataFrame 名称作为字典键来存储所有中间 DataFrame。

假设原始DataFrame命名为df

aggHierarchy = [['job', ['year', 'area', 'ind', 'occ']],
                ['work', ['year', 'area', 'ind']],
                ['county', ['year', 'area']],
                ['year', ['year']]]

data_frames = {}
for df_name, group in aggHierarchy:
    df = df.groupby(group, as_index=False)
    df = df.agg(aggVars)
    data_frames[df_name] = df

如果不想丢失原来的DataFrame:

data_frames = {}
new_df = df
for df_name, group in aggHierarchy:
    new_df = new_df.groupby(group, as_index=False)
    new_df = new_df.agg(aggVars)
    data_frames[df_name] = new_df

您的评论:

如果在 aggHierarchy 中,我将名称列为 df_industry、df_area 等,然后在 aggHierarchy 中使用 for df_name、group 循环,结果字典键为行业、区域等。也就是说,当前缀包含在循环变量中并且事物循环过去时,python似乎“吸收”了前缀。

当我看到它时让我感到惊讶 - 我当然没有看到这种行为

aggHierarchy = [['df_job', ['year', 'area', 'ind', 'occ']],
                ['df_work', ['year', 'area', 'ind']],
                ['df_county', ['year', 'area']],
                ['df_year', ['year']]]

d = {}
for df_name, thing in aggHierarchy:
    print(df_name, thing)
    d[df_name] =  thing

>>>
df_job ['year', 'area', 'ind', 'occ']
df_work ['year', 'area', 'ind']
df_county ['year', 'area']
df_year ['year']
>>>
>>> d
{'df_job': ['year', 'area', 'ind', 'occ'], 'df_work': ['year', 'area', 'ind'], 'df_county': ['year', 'area'], 'df_year': ['year']}
>>>
>>> d['df_year']
['year']
>>> d['year']
Traceback (most recent call last):
  File "<pyshell#206>", line 1, in <module>
    d['year']
KeyError: 'year'
>>>

在循环中,df_namejust a namefor statement 隐含(?)assigning aggHierarchy 中每个 row 到它的第一项。没有魔法。

【讨论】:

  • 太棒了。这确实会产生相同的结果!现在我要坐一会儿,弄清楚它为什么起作用。 (我使用 Stata 进行数据分析超过 15 年,而 Stata 没有字典结构。因此我仍然没有直觉。)感谢您快速而有用的回复。
  • @JPFerguson,有什么你想弄清楚的具体问题WHY
  • 有时Python Names 起初也会绊倒人。
  • 此时,没有。我现在明白字典正在将这些名称链接到数据框。根据我链接到的一篇帖子:“所有这些的共同点是试图弥合两个域之间的差距:程序中的数据和程序中的数据名称。任何时候发生这种情况,都很清楚表示您需要在数据建模中上移一个级别。您需要一个字典,而不是 26 个列表。而不是 N 个表,您应该有一个表,其中多一列。我明白这如何为我们提供了一个数据框字典,而不是一组杂乱无章的变量。
  • 其实@wwii,一个具体的问题,如果你不介意的话。如果在 aggHierarchy 中,我将名称列为df_industrydf_area 等,然后使用for df_name, group in aggHierarchy 循环,则生成的字典键为industryarea 等。也就是说,当前缀包含在循环变量中并且事物循环时,python似乎“吸收”了前缀。如果我保留这样的名称并使用for name, group... 循环,则不会发生这种情况。这种现象叫什么,所以我可以阅读它?如果我不明白,这似乎是一个未来的地雷。
猜你喜欢
  • 1970-01-01
  • 2014-03-15
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2015-11-04
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多