我需要用单索引更新一个多索引数据框。新数据框是旧数据框的子集,只是具有新值,因此不会创建新的列或行。仅更新选定的片,这需要支持一次更新多个列。我希望熊猫自动进行行索引解析,并且只覆盖提供的行。
是否可以在熊猫0.24.2中以API本地方式完成此操作而没有循环,自定义功能,重置索引或创建多索引? (如果无法切片和更新,那么具有多索引的意义是什么?)我搜索了其他问题,但没有找到适用于此特定用例或提供优雅解决方案的最新答案。>
这是一些代码。
df_old = pd.DataFrame(
[['a', 'x', 0, 0, 0], ['a', 'y', 0, 0, 0], ['a', 'z', 0, 0, 0],
['b', 'x', 0, 0, 0], ['b', 'y', 0, 0, 0], ['b', 'z', 0, 0, 0],
],
columns=['i1', 'i2', 'c1', 'c2', 'c3']).set_index(['i1', 'i2'])
df_new = pd.DataFrame([['x', 1, 2], ['y', 3, 4]],
columns=['i2', 'c1', 'c2']).set_index('i2')
df_old
Out[]:
c1 c2 c3
i1 i2
a x 0 0 0
y 0 0 0
z 0 0 0
b x 0 0 0
y 0 0 0
z 0 0 0
df_new
Out[]:
c1 c2
i2
x 1 2
y 3 4
理想情况下,我希望下面的单行命令起作用,但它绝对不起作用。甚至没有任何警告弹出。我也尝试过合并,但无济于事。
df_old.loc[idx['a'], :].update(df_new)
预期结果如下所示,其中仅更新所选的“ a”片。
c1 c2 c3
i1 i2
a x 1 2 0
y 3 4 0
z 0 0 0
b x 0 0 0
y 0 0 0
z 0 0 0
dataframe summary in one clear picture
谢谢!
答案 0 :(得分:0)
如果(1)df_new
中的每个索引在df_old
中都有对应的索引,则该解决方案对我有用。
(2)i2
索引的顺序在df_old
和df_new
中是相同的。之所以需要第二个约束,是因为左侧切片的元素顺序遵循df_old
中的顺序,而不是df_new.index
中的顺序。我不确定这是错误还是预期的行为。
df_old.loc[('a', df_new.index), df_new.columns] = df_new.values
有关here的MultiIndex切片的更多信息。
答案 1 :(得分:0)
GZ0提供的解决方案是迄今为止为多索引更新数据帧的一部分而实际工作的少数解决方案之一。但这对于我的情况来说非常缓慢(每800个数据点取9s)。速度缓慢主要是因为我们正在查找要写入的索引。
我下面的解决方案是对GZ0解决方案的扩展,可以解决我的特定情况,每只猫运行大约110毫秒(大约800个数据点)。此解决方案仅通过遵循subcat从df的原始顺序而不是匹配单个索引来覆盖整个系列。可能不是每个人都适合的解决方案。
场景: 我只有两个级别的行索引(cat,subcat),并且在一个字段(input_field_col)上为所有子类别的Cat(逐个类别)运行滚动时间序列计算。此时间序列calc的结果会在原始数据帧中创建一个新的数据序列列。
ds = df.loc[cat,input_field_col].rolling(winlen).mean()
df.loc[cat,new_col] = ds.values