python 字典理解如何与内部的 lambda 函数一起工作
How does python dict comprehension work with lambda functions inside
我的目标是使用 agg 函数聚合一个 pandas DataFrameGroupBy 对象。
为了做到这一点,我正在生成一个字典,我将通过 **dict
使用 dict 解包将其解包为 kwargs。这个字典需要包含新的列名作为键和一个元组作为值。元组的第一个值是列名,它被压缩成一个系列并作为 lambda series: ...
.
的输入提供给第二个值
agg_dict = {
f"{cat_name}_count": ('movement_state', lambda series: series.value_counts()[cat_name])
for cat_name in ml_data['category_column'].cat.categories
}
# Aggregating
agg_ml_data = ml_data.groupby(['col1', 'col2']).agg(**agg_dict)
现在实际发生的事情对我来说有点奇怪。
假设:
ml_data['category_column'].cat.categories
Index(['cat1', 'cat2', 'cat3'], dtype='object')
一组的正确计数是
one_group['category_column'].value_counts()
| category_column
cat1 | 2
cat2 | 9
cat3 | 6
一组的预期输出:
cat1_count
cat2_count
cat3_count
2
9
6
一组实际产量
cat1_count
cat2_count
cat3_count
6
6
6
不知何故,python 未按预期执行 lambda 函数的字典理解,并且在索引 series.value_counts()[cat_name]
时仅使用最后一个类别值 cat3
。我希望 lambda 函数是像字典本身一样创建的。关于如何解决该问题的任何想法?
这是一个经典的 Python 陷阱。
当您在 lambda 表达式中使用自由变量(cat_name
,在本例中)时,lambda 捕获名称引用的变量,而不是该变量的值。所以在这种情况下,lambda“记住” cat_name
是“该字典理解的循环变量”。当 lambda 被调用时,它会查找“那个字典理解的循环变量”的值,现在,由于字典理解已经完成,它仍然是列表的最后一个值。
解决这个问题的常用方法是使用默认参数来“冻结”该值,例如
lambda series, cat=cat_name: series.blah[cat]
有效地使用一个陷阱(Python 在函数定义时计算默认参数)爬出另一个陷阱。 :-)
我的目标是使用 agg 函数聚合一个 pandas DataFrameGroupBy 对象。
为了做到这一点,我正在生成一个字典,我将通过 **dict
使用 dict 解包将其解包为 kwargs。这个字典需要包含新的列名作为键和一个元组作为值。元组的第一个值是列名,它被压缩成一个系列并作为 lambda series: ...
.
agg_dict = {
f"{cat_name}_count": ('movement_state', lambda series: series.value_counts()[cat_name])
for cat_name in ml_data['category_column'].cat.categories
}
# Aggregating
agg_ml_data = ml_data.groupby(['col1', 'col2']).agg(**agg_dict)
现在实际发生的事情对我来说有点奇怪。
假设:
ml_data['category_column'].cat.categories
Index(['cat1', 'cat2', 'cat3'], dtype='object')
一组的正确计数是
one_group['category_column'].value_counts()
| category_column
cat1 | 2
cat2 | 9
cat3 | 6
一组的预期输出:
cat1_count | cat2_count | cat3_count |
---|---|---|
2 | 9 | 6 |
一组实际产量
cat1_count | cat2_count | cat3_count |
---|---|---|
6 | 6 | 6 |
不知何故,python 未按预期执行 lambda 函数的字典理解,并且在索引 series.value_counts()[cat_name]
时仅使用最后一个类别值 cat3
。我希望 lambda 函数是像字典本身一样创建的。关于如何解决该问题的任何想法?
这是一个经典的 Python 陷阱。
当您在 lambda 表达式中使用自由变量(cat_name
,在本例中)时,lambda 捕获名称引用的变量,而不是该变量的值。所以在这种情况下,lambda“记住” cat_name
是“该字典理解的循环变量”。当 lambda 被调用时,它会查找“那个字典理解的循环变量”的值,现在,由于字典理解已经完成,它仍然是列表的最后一个值。
解决这个问题的常用方法是使用默认参数来“冻结”该值,例如
lambda series, cat=cat_name: series.blah[cat]
有效地使用一个陷阱(Python 在函数定义时计算默认参数)爬出另一个陷阱。 :-)