dask 中的奇怪行为适用于 lambda 函数循环
Strange behaviour in dask apply with loop of lambda functions
我不确定这是 dask 的错误还是 python 的功能。简单示例:
data = pd.DataFrame({'tags': [['dog'], ['cat', 'red'], ['cat'], ['cat', 'red'], ['cat', 'red'], ['dog', 'red']]})
print data
tags
0 [dog]
1 [cat, red]
2 [cat]
3 [cat, red]
4 [cat, red]
5 [dog, red]
我想为每个标签创建"hot-columns"
tags = ['cat', 'dog', 'red']
使用 dask:
data = dd.from_pandas(data, npartitions=4)
for tag in tags:
data[tag] = data.tags.apply(lambda x: tag in x, meta=(tag, bool))
结果错误:
print data.compute()
tags cat dog red
0 [dog] False False False
1 [cat, red] True True True
2 [cat] False False False
3 [cat, red] True True True
4 [cat, red] True True True
5 [dog, red] True True True
似乎 lambda
总是绑定到循环中的最后一个标签 (red
)。如果我手动展开循环,它会正常工作。
使用普通 pandas 我没有这个问题。
部分解决方案
def is_in(items, value):
return value in items
for tag in tags:
data[tag] = data.tags.apply(is_in, value=tag, meta=(tag, bool))
我不太喜欢它,因为它迫使参数的顺序非常不自然。顺便说一句,我不确定是否理解了原始问题。
答案在这里:What do (lambda) function closures capture?,它是关于 python 的词法范围的。
更好的解决方案:对 lambda 使用默认值
for tag in tags:
data[tag] = data.tags.apply(lambda x, t=tag: t in x, meta=(tag, bool))
我不确定这是 dask 的错误还是 python 的功能。简单示例:
data = pd.DataFrame({'tags': [['dog'], ['cat', 'red'], ['cat'], ['cat', 'red'], ['cat', 'red'], ['dog', 'red']]})
print data
tags
0 [dog]
1 [cat, red]
2 [cat]
3 [cat, red]
4 [cat, red]
5 [dog, red]
我想为每个标签创建"hot-columns"
tags = ['cat', 'dog', 'red']
使用 dask:
data = dd.from_pandas(data, npartitions=4)
for tag in tags:
data[tag] = data.tags.apply(lambda x: tag in x, meta=(tag, bool))
结果错误:
print data.compute()
tags cat dog red
0 [dog] False False False
1 [cat, red] True True True
2 [cat] False False False
3 [cat, red] True True True
4 [cat, red] True True True
5 [dog, red] True True True
似乎 lambda
总是绑定到循环中的最后一个标签 (red
)。如果我手动展开循环,它会正常工作。
使用普通 pandas 我没有这个问题。
部分解决方案
def is_in(items, value):
return value in items
for tag in tags:
data[tag] = data.tags.apply(is_in, value=tag, meta=(tag, bool))
我不太喜欢它,因为它迫使参数的顺序非常不自然。顺便说一句,我不确定是否理解了原始问题。
答案在这里:What do (lambda) function closures capture?,它是关于 python 的词法范围的。
更好的解决方案:对 lambda 使用默认值
for tag in tags:
data[tag] = data.tags.apply(lambda x, t=tag: t in x, meta=(tag, bool))