Панды MultiIndex назначают несколько столбцов - PullRequest
1 голос
/ 21 октября 2019

Я создал фрейм данных с MultiIndex, как показано ниже:

import numpy as np
import pandas as pd
column_index= [np.array(['OPEN','OPEN','CLOSE','CLOSE']),np.array(['IBM','AAPL','IBM','AAPL'])]
df = pd.DataFrame(np.transpose(np.array([[1,2,3],[4,5,6],[7,8,9],[10,11,12]])),index=['20190101','20190102','20190103'],columns=column_index)

Результат примерно такой:

          OPEN          CLOSE
          IBM   AAPL    IBM AAPL
20190101    1    4      7   10
20190102    2    5      8   11
20190103    3    6      9   12

Теперь я хотел бы создать новый набор столбцовделая что-то вроде:

df['RTN'] = df.CLOSE / df.OPEN

Чтобы получить:

            OPEN      CLOSE       RTN
            IBM AAPL  IBM   AAPL  IBM   AAPL
20190101    1   4     7     10    7.0   2.5
20190102    2   5     8     11    4.0   2.2
20190103    3   6     9     12    3.0   2.0

Это не работает. Самый хороший способ, которым я смог сделать это, выглядит так:

rtn = df.CLOSE / df.OPEN
rtn = pd.concat([rtn],keys=['RTN'],axis=1)
df = pd.concat([df,rtn],axis=1)

Есть ли способ сделать это как задание без других шагов?

1 Ответ

1 голос
/ 21 октября 2019

Один из способов - rename столбцы перед операциями. Тогда это простой конкат:

u = df.loc[:, ['CLOSE']].rename(columns={'CLOSE': 'RTN'}, level=0).divide(
        df.loc[:, ['OPEN']].rename(columns={'OPEN': 'RTN'}, level=0))
                   # [] DataFrame selection keeps MultiIndex

pd.concat([df, u], axis=1)

Кроме того, вы можете stack + eval + unstack. Это сжато, но, возможно, не супер производительность для больших наборов данных.

df.stack().eval('RTN = CLOSE/OPEN').unstack()
#df.stack().assign(RTN = lambda x: x.CLOSE/x.OPEN).unstack()

Без eval:

df.stack().assign(RTN = lambda x: x.CLOSE/x.OPEN).unstack()

#or 

df = df.stack()
df['RTN'] = df.CLOSE/df.OPEN
df = df.unstack()

Вывод во всех случаях:

         OPEN      CLOSE       RTN     
          IBM AAPL   IBM AAPL  IBM AAPL
20190101    1    4     7   10  7.0  2.5
20190102    2    5     8   11  4.0  2.2
20190103    3    6     9   12  3.0  2.0
...