I am trying to understand pandas
MultiIndex
DataFrame
s and how to assign data to them. Specifically I'm interested in assigning entire blocks that match another smaller data frame.
ix = pd.MultiIndex.from_product([['A', 'B'], ['a', 'b', 'c', 'd']])
df = pd.DataFrame(index=ix, columns=['1st', '2nd', '3rd'], dtype=np.float64)
df_ = pd.DataFrame(index=['a', 'b', 'c', 'd'], columns=['1st', '2nd', '3rd'], data=np.random.rand(4, 3))
df_
1st 2nd 3rd
a 0.730251 0.468134 0.876926
b 0.104990 0.082461 0.129083
c 0.993608 0.117799 0.341811
d 0.784950 0.840145 0.016777
df
is the same except that all the values are NaN
and there are two blocks A
and B
. Now if I want to assign the values from df_
to df
I would imagine I can do something like
df.loc['A',:] = df_ # Runs, does not work
df.loc[('A','a'):('A','d')] = df_ # AssertionError (??) 'Start slice bound is non-scalar'
df.loc[('A','a'):('A','d')] # No AssertionError (??)
idx = pd.IndexSlice
df.loc[idx['A', :]] = df_ # Runs, does not work
None of these work, they leave all the values in df
as NaN
, although df.loc[idx['A', :]]
gives me a slice of the data frame that exactly matches that of the sub frame (df_
). So is this a case of setting values on a view? Explicitly iterating over the index in df_
works
# this is fine
for v in df_.index:
df.loc[idx['A', v]] = df_.loc[v]
# this is also fine
for v in df_.index:
df.loc['A', v] = df_.loc[v]
Is it even possible to assign whole blocks like this (sort of like NumPy
)? If not, that's fine, I am simply trying to understand how the system works.
There's a related question about index slicers, but it's about assigning a single value to a masked portion of the DataFrame
, not about assigning blocks.
Pandas : Proper way to set values based on condition for subset of multiindex dataframe