我正在使用带有混合索引标签的多索引数据框,即第一级包含字符串标签,第二级和第三级是整数标签,第四级标签是日期。 Dataframe如下所示(master_df)
X1 X2 X3
bucket Start Stop Date
B1 1 1 1/3/2000 2 2 3
1/4/2000 4 3 3
B1 1 2 1/3/2000 4 2 3
1/4/2000 6 2 2
我想取出sub_df作为master_df.ix ['B1',1,2,:],对sub_df执行一些操作并将其存储回master_df中的相同位置。我可以使用各种方法取出sub_df,但是当把它存回来时,我试过的所有选项似乎都没有用。我想这个问题与'Integer'标签有关(在第2和第3个lavel - start-stop)。我尝试过以下选项/方法但没有成功
sub_df = master_df.ix['B1'].ix[1].ix[2]
#do some operations on sub_df
master_df.xs('B1').xs(1).xs(2).update(sub_df)
master_df.ix['B1'].ix[1].ix[2].update(sub_df)
merge(master_df.ix['B1',1,2,:],sub_df)
以上操作均未反映master_df中的更改(我也没有收到任何错误消息。)
你能建议正确的方法吗?
更新:
sub_df和master_df与sub_df expect date index上的操作没有相同的索引。 sub_df如下所示。
X1 X2 X3
Date
1/3/2000 2 2 3
1/4/2000 4 3 3
如果我尝试
sub_df = master_df[master_df.index.get_loc(('B1', 1, 2))]
我收到以下错误 -
TypeError:不可用类型:'numpy.ndarray'
此处的主要目的是仅对master_df的一小部分进行操作,并将这些结果存储在master_df中的原始位置。我尝试使用更新方法,但是实现此目的的任何其他替代方法都可以。
答案 0 :(得分:2)
这并不能完全解决您的问题,但我可能会这样做 提供一些灵感
这是一种直接设置值的方法
In [75]: df
Out[75]:
bucket start stop date x1 x2 x3
0 B1 1 1 2000-10-03 00:00:00 2 2 3
1 B1 1 1 2000-01-04 00:00:00 4 3 3
2 B1 1 2 2000-01-03 00:00:00 4 2 3
3 B1 1 2 2000-01-04 00:00:00 6 2 2
In [76]: df2 = df.set_index(['bucket','start','stop'])
In [77]: df2
Out[77]:
date x1 x2 x3
bucket start stop
B1 1 1 2000-10-03 00:00:00 2 2 3
1 2000-01-04 00:00:00 4 3 3
2 2000-01-03 00:00:00 4 2 3
2 2000-01-04 00:00:00 6 2 2
In [78]: df2.ix[('B1',1,2)].ix[:,'x1'] = 5
In [79]: df2
Out[79]:
date x1 x2 x3
bucket start stop
B1 1 1 2000-10-03 00:00:00 2 2 3
1 2000-01-04 00:00:00 4 3 3
2 2000-01-03 00:00:00 5 2 3
2 2000-01-04 00:00:00 5 2 2
这是另一种方法,你选择一个具有多索引的系列,修改它, 然后将其分配回来(仅适用于系列)。
In [89]: df2.ix[:,'x1']
Out[89]:
bucket start stop
B1 1 1 2
1 4
2 4
2 6
Name: x1, dtype: int64
In [90]: new_s = df2.ix[:,'x1'].copy()
In [91]: new_s
Out[91]:
bucket start stop
B1 1 1 2
1 4
2 4
2 6
Name: x1, dtype: int64
# can also do a more complicated selctor than the 0th row
In [92]: new_s[0] = 5
In [93]: new_s
Out[93]:
bucket start stop
B1 1 1 5
1 4
2 4
2 6
Name: x1, dtype: int64
In [94]: df2.ix[:,'x1'] = new_s
In [95]: df2
Out[95]:
date x1 x2 x3
bucket start stop
B1 1 1 2000-10-03 00:00:00 5 2 3
1 2000-01-04 00:00:00 4 3 3
2 2000-01-03 00:00:00 4 2 3
2 2000-01-04 00:00:00 6 2 2
这是您在0.11
中可以做的事情# this is sessentially saying give me the first 2 rows (equivalent
# to selecting via complicated tuple)
In [107]: df2.iloc[0:2,:]
Out[107]:
date x1 x2 x3
bucket start stop
B1 1 1 2000-10-03 00:00:00 10 2 3
1 2000-01-04 00:00:00 4 3 3
In [108]: df2.iloc[0:2,:].loc[:,'x1']
Out[108]:
bucket start stop
B1 1 1 10
1 4
Name: x1, dtype: int64
In [109]: df2.iloc[0:2,:].loc[:,'x1'] = 5
In [110]: df2
Out[110]:
date x1 x2 x3
bucket start stop
B1 1 1 2000-10-03 00:00:00 5 2 3
1 2000-01-04 00:00:00 5 3 3
2 2000-01-03 00:00:00 4 2 3
2 2000-01-04 00:00:00 6 2 2
答案 1 :(得分:1)
sub_df
与master_df
具有相同的索引非常重要。
获取正确索引的一种方法是使用get_loc
:
sub_df = df[df.index.get_loc(('B1', 1, 2))]
# operations not changing index
master_df.update(sub_df)
答案 2 :(得分:0)
谢谢大家的帮助。最后,我从2级和3级的数字索引切换到charater索引,现在情况正常(这也有助于在级别上进行正确的排序,这是我认为使事情更加明确。)
答案 3 :(得分:0)
对于您给出的示例(选择('B1',1,2,...)),您可以使用xs iso ix。与ix相比,xs可以在使用标签时返回数据视图(有关ix返回视图/副本的更多详细信息,请参阅docs)。 在下面的示例中,sub_df的colum X1是更改,这也会影响master_df。
In [48]: master_df
Out[48]:
X1 X2 X3
bucket Start Stop Date
B1 1 1 2000-01-03 2 2 3
2000-01-04 4 3 3
2 2000-01-03 4 2 3
2000-01-04 6 2 2
In [49]: sub_df = master_df.xs(['B1', 1, 2], copy=False)
In [50]: sub_df
Out[50]:
X1 X2 X3
Date
2000-01-03 4 2 3
2000-01-04 6 2 2
In [51]: sub_df.X1 -= 4
In [52]: sub_df
Out[52]:
X1 X2 X3
Date
2000-01-03 0 2 3
2000-01-04 2 2 2
In [53]: master_df
Out[53]:
X1 X2 X3
bucket Start Stop Date
B1 1 1 2000-01-03 2 2 3
2000-01-04 4 3 3
2 2000-01-03 0 2 3
2000-01-04 2 2 2
答案 4 :(得分:0)
在0.13参数中,'drop_level'已添加到'xs',这样就可以解决您的问题,因为所有索引级别都将出现在sub_df中:
sub_df = master_df.xs(['B1',1,2],level = ['bucket','Start','Stop'],drop_level = False)
现在合并将有效。
没试过,但它应该有用。