0
import pandas as pd
import numpy as np

df = pd.DataFrame(np.zeros([4,1]), index=pd.MultiIndex.from_product([[0,1], ['a','b']]))
df.loc[(slice(None), 'a'), 0] = pd.Series({1:2, 0:3})
df

gives

enter image description here

I found a couple of places that recommend adding .values to the right hand side, but that gives wrong results here (it gets the 2 and 3 switched because I intentionally put my right hand side series in a "wrong" order), because I do need pandas to align for me, but only based on the zeroth level. How can I get

enter image description here

Bananach
  • 1,753
  • 18
  • 43
  • 1
    @anky I kind of get what you mean, but that's just vagueness of words, which is why I included an example that shows more clearly what I want than words could. – Bananach Feb 01 '21 at 00:16
  • Hopefully the answer is helpful. Thoroughly answering questions is time-consuming. If your question is **solved**, please _**accept** the solution_. The **✔** is below the **▲/▼** arrow, at the top left of the answer. A new solution can be accepted if a better one shows up. You may also vote on the usefulness of an answer, with the **▲/▼** arrow, if you have a 15+ reputation. **Leave a comment if a solution doesn't answer the question.** [What should I do when someone answers my question?](https://stackoverflow.com/help/someone-answers). Thank you. – Trenton McKinney Feb 04 '21 at 19:46

1 Answers1

1

Update Selected Slice of Multi-Index DataFrame

  • Use multiindex slicing with pd.IndexSlice, which creates an object to more easily perform multi-index slicing.
  • Caveats:
    • The multi-index dataframe and the Series used to update it, must be sorted on the index
    • The number of values in the Series and the multi-index dataframe, must be the same.
import pandas as pd

# dataframe
df = pd.DataFrame(np.zeros([4,1]), index=pd.MultiIndex.from_product([[0,1], ['a','b']]))

# series
s = pd.Series({1:2, 0:3})

# update the desired values where index level 1 is a
idx = pd.IndexSlice
df.loc[idx[:, ['a']], :] = s.sort_index().tolist()

# display(df)
       0
0 a  3.0
  b  0.0
1 a  2.0
  b  0.0

Add Index Level to Series and then Update

  • The series index will never match the the multi-index dataframe, so updating in the manner suggested in the OP, is not an option, therefore you must update the series to match the multi-index.
  • Use pandas.MultiIndex.from_tuples with a list-comprehension to create a new index for s
# dataframe
df = pd.DataFrame(np.zeros([4,1]), index=pd.MultiIndex.from_product([[0,1], ['a','b']]))

# series
s= pd.Series({1:2, 0:3})

# add another level to the series index and then update
s.index = pd.MultiIndex.from_tuples([(i, 'a') for i in s.index])

# update df from s
df.update(s)

# display(df)
       0
0 a  3.0
  b  0.0
1 a  2.0
  b  0.0

Update Multi-Index DataFrame from Multi-Index DataFrame

  • To update the multi-index dataframe by index, the object being updated from, must be multi-index
# dataframe
df = pd.DataFrame(np.zeros([4,1]), index=pd.MultiIndex.from_product([[0,1], ['a','b']]))

# object used to update df
arrays = [[1, 0], ['a', 'a']]
idx = pd.MultiIndex.from_arrays(arrays)
s = pd.DataFrame({0: [2, 3]}, index=idx)

# display(s)
     0
1 a  2
0 a  3

# update df using s; this is an inplace update
df.update(s)

# display(df)
       0
0 a  3.0
  b  0.0
1 a  2.0
  b  0.0
Trenton McKinney
  • 43,885
  • 25
  • 111
  • 113