python - 在 pandas groupby 对象上重新运行 agg 会修改原始数据框
问题描述
我正在尝试聚合一堆字典,将字符串键和二进制数列表作为值,存储在熊猫数据框中。像这样:
发生此问题的示例数据框:
df4
subject task_nr probe_dict
0 2 1 {'1_3': [0, 0, 1, 1]}
1 2 0 {'1_3': [0, 0, 1, 1]}
2 2 0 {'1_3': [0, 0, 1, 1]}
对于聚合,我只想在数据帧不同行中的字典中的键相等时将列表连接在一起。在聚合之前,我运行一个 groupby 操作,主题和 task_nr 作为“groupers”。我的聚合函数有一个参数,让我只从加入列表中获取最后 n 个条目。我想用不同的参数重新运行它。但是,当我多次在从数据帧派生的 groupby 对象上重新运行 .agg 时,原始数据帧会发生变化。下面是我的 groupby 和聚合代码。我已经包含了一些深拷贝来试图避免这个问题,但它似乎没有帮助。原因似乎是原始数据框正在被修改。有没有办法避免这种情况?为什么会这样?
grouped= cp.deepcopy(df4).groupby(['subject','task_nr']) #group results by task and subject
mptd_only30 = partial(merge_probe_trial_dicts,only_last=30) #consider only last 30 probe trials
mergag = cp.deepcopy(grouped['probe_dict']).agg(mptd_only30) #aggregate data across sessions using function above
聚合函数。
def merge_probe_trial_dicts(x,only_last=None):
"""
Function passed as argument to result of pandas groupby in
order to merge the dicts by subject and task
Arguments:
=========================
x: what is passed by agg
only_last (int): only look at the last n probe trials for each transition
"""
out = {}
for d in x.dropna():
for k,v in d.items():
if k not in out.keys():
out[k] = v
else:
out[k].extend(v)
if only_last:
for k,v in out.items():
out[k] = v[-only_last:]
return out
解决方案
问题是它会merge_probe_trial_dicts
改变原来的列表df4
而不是创建一个新列表。
只需添加.copy()
如下,你应该很好。
def merge_probe_trial_dicts(x, only_last=None):
out = {}
for d in x.dropna():
for k, v in d.items():
if k not in out.keys():
out[k] = v.copy() # This is the trick
else:
out[k].extend(v)
if only_last:
for k,v in out.items():
out[k] = v[-only_last:]
return out
附加技巧:将额外的参数agg
传递给聚合函数。所以你可以直接这样做:
df4.groupby(["subject", "task_nr"]).agg(merge_probe_trial_dicts, only_last=30)
代替:
mptd_only30 = partial(merge_probe_trial_dicts, only_last=30)
df4.groupby(["subject", "task_nr"]).agg(mptd_only30)
另一个:if k not in out.keys()
效率很低,因为您out.keys()
每次都重新计算。我建议defaultdict
改用更简单、更高效的代码:
from collections import defaultdict
def merge_probe_trial_dicts(x, only_last=None):
out = defaultdict(list)
for d in x.dropna():
for key, value in d.items():
out[key] += value
if only_last is not None:
for key, value in out.items():
out[key] = value[-only_last:]
return out
推荐阅读
- javascript - 如何在 http 中调用 facebook SDK?
- python - 在 Python 中重写 Mathematica 输出
- mysql - 从 MySQL 数据库中导出索引表
- c# - 使用 asp 标签助手时显示真正的运行时超链接
- oracle - Oracle Application Express 中的报告页错误
- powerbi - Power BI 中的详细到详细钻取
- android - RecyclerView中的WebView显示虚假数据
- excel - Excel Userform 加载时的动画点
- c# - 在一个事件中重新组合按钮事件
- c# - 编写 NUnit 测试时的类型冲突