【问题标题】:How to iterate over Multiindex and multiply two columns in Pandas?如何在 Pandas 中迭代 Multiindex 并将两列相乘?
【发布时间】:2019-02-05 20:07:31
【问题描述】:

我想遍历 Multiindex 并将“2017-01-01”月的第一天的“供应”列(前 10 个“符号”,已经排名)乘以“价格”(相同的 10 个符号)在每个月的每一天直到月底,并将值存储在新列“New.Cap”中,并为每个月重复相同的操作。

我尝试了一个 for 循环,但无法使其工作。我能够获得前 10 名的“供应”值并将其乘以第二天的价格(相同的“符号”)并将其存储为“2017-01-02”

我的数据框:

    Date    Symbol   Market.Cap  Price   Circulating.Supply
    1/1/2017    BTC 16050414526 998.33  16077337
    1/1/2017    ETH 715049311   8.17    87493800
    1/1/2017    XRP 231408729   0.01    36337298649
    1/1/2017    LTC 221718486   4.51    49144154
    1/1/2017    XMR 190983552   13.97   13668252
    1/1/2017    ETC 122202804   1.4      87444118
    1/1/2017   DASH 78524020    11.23    6992839
    1/1/2017    REP 43994860    4        11000000
    1/1/2017    MAID 43862003   0.1     452552412
    1/1/2017    STEEM  36999610 0.16    229582096
    1/1/2017    XEM 30962258    0       8999999999
    1/1/2017    ICN 26381302    0.3      87000000
    1/1/2017    FCT 25392986    2.9     8753219
    1/1/2017   DOGE 24501946    0    1.07544E+11
    1/1/2017   WAVES 22132166   0.22 100000000
    1/1/2017    DGD  18079172   9.04      2000000
    1/2/2017    BTC 16429072864 1021.75 16079300
    1/2/2017    ETH 733331862   8.38    87525306
    1/2/2017    XRP 229312859   0.01    36337298649
    1/2/2017    LTC 228536428   4.65    49158829
    1/2/2017    XMR 219509938   16.05   13675283
    1/2/2017    ETC 125743676   1.44    87476792
    1/2/2017    DASH    82595831    11.81   6994957
    1/2/2017    REP 46101566    4.19    11000000
    1/2/2017    MAID    42320210    0.09    452552412
    1/2/2017    STEEM   35374447    0.15    229645428
    1/2/2017    XEM 30396875    0   8999999999
    1/2/2017    ICN 26451766    0.3 87000000
    1/2/2017    FCT 26119449    2.98    8753219
    1/2/2017    DOGE    24343443    0   1.07557E+11
    1/2/2017    WAVES   23267904    0.23    100000000
    1/2/2017    ZEC 17773124    49.79   356994
    1/3/2017    BTC 16786354619 1043.84 16081362
    1/3/2017    ETH 851511659   9.73    87556829
    1/3/2017    XRP 232046528   0.01    36337298649
    1/3/2017    LTC 227483720   4.63    49172954
    1/3/2017    XMR 220176407   16.09   13681607
    1/3/2017    ETC 130608332   1.49    87508802
    1/3/2017    DASH    89434687    12.78   6997071
    1/3/2017    REP 46955890    4.27    11000000
    1/3/2017    MAID    44863660    0.1 452552412
    1/3/2017    STEEM   36308540    0.16    229753160
    1/3/2017    XEM 32157836    0   8999999999
    1/3/2017    ICN 29520641    0.34    87000000
    1/3/2017    FCT 27402737    3.13    8753219
    1/3/2017    DOGE    24429805    0   1.07571E+11
    1/3/2017    WAVES   23992972    0.24    100000000

索引列是前两个(日期和符号)。

这是我目前所拥有的:

    df = pd.read_csv(file_path, parse_dates=['Date'], index_col='Date')
    df = df.set_index('Symbol', append=True)  
    s = df['Circulating.Supply'].xs('2017-01-01') * df['Price'].xs('2017-01- 02')
    s.index = [np.repeat(pd.Timestamp('2017-01-02'), len(s)), s.index]
    df['New.Cap'] = s
    print(df['New.Cap'].loc['2017-01-02'])

【问题讨论】:

  • 运行 df['Circulating.Supply'].xs('2017-01-01') * df['Price'].xs('2017-01-02') 给了我所有的 NaN,因为日期不同。
  • 请打印它以供 print(df['New.Cap'].loc['2017-01-02']) 查看值。
  • df['New.Cap'] = s 给出 ValueError 并失败,所以我不能
  • 我假设Date 是开始的索引col?
  • 抱歉,我忘记指定索引了。 'Date' 和 'Symbol' 是索引,这就是你可能得到 ValueError 的原因。

标签: pandas multi-index


【解决方案1】:

你可以使用:

#get top10 rows per datetimes in DatetimeIndex
df = df.groupby(level=0).head(10)

#create MultiIndex
df1 = df.set_index('Symbol', append=True)
#print (df1)

#subtract one day and create MultiIndex
df2 = df.set_index(df.index - pd.Timedelta(1, unit='d')).set_index('Symbol', append=True)
#print (df2)

#multiple both Series from first and second DataFrame
df1['new'] = df1['Circulating.Supply'] * df2['Price']
print (df1)
                    Market.Cap    Price  Circulating.Supply           new
Date       Symbol                                                        
2017-01-01 BTC     16050414526   998.33        1.607734e+07  1.642702e+10
           ETH       715049311     8.17        8.749380e+07  7.331980e+08
           XRP       231408729     0.01        3.633730e+10  3.633730e+08
           LTC       221718486     4.51        4.914415e+07  2.285203e+08
           XMR       190983552    13.97        1.366825e+07  2.193754e+08
           ETC       122202804     1.40        8.744412e+07  1.259195e+08
           DASH       78524020    11.23        6.992839e+06  8.258543e+07
           REP        43994860     4.00        1.100000e+07  4.609000e+07
           MAID       43862003     0.10        4.525524e+08  4.072972e+07
           STEEM      36999610     0.16        2.295821e+08  3.443731e+07
2017-01-02 BTC     16429072864  1021.75        1.607930e+07  1.678422e+10
           ETH       733331862     8.38        8.752531e+07  8.516212e+08
           XRP       229312859     0.01        3.633730e+10  3.633730e+08
           LTC       228536428     4.65        4.915883e+07  2.276054e+08
           XMR       219509938    16.05        1.367528e+07  2.200353e+08
           ETC       125743676     1.44        8.747679e+07  1.303404e+08
           DASH       82595831    11.81        6.994957e+06  8.939555e+07
           REP        46101566     4.19        1.100000e+07  4.697000e+07
           MAID       42320210     0.09        4.525524e+08  4.525524e+07
           STEEM      35374447     0.15        2.296454e+08  3.674327e+07
2017-01-03 BTC     16786354619  1043.84        1.608136e+07           NaN
           ETH       851511659     9.73        8.755683e+07           NaN
           XRP       232046528     0.01        3.633730e+10           NaN
           LTC       227483720     4.63        4.917295e+07           NaN
           XMR       220176407    16.09        1.368161e+07           NaN
           ETC       130608332     1.49        8.750880e+07           NaN
           DASH       89434687    12.78        6.997071e+06           NaN
           REP        46955890     4.27        1.100000e+07           NaN
           MAID       44863660     0.10        4.525524e+08           NaN
           STEEM      36308540     0.16        2.297532e+08           NaN

编辑:

每个月的第一天获取前 10 个值,通过 unstack 重塑并将索引设置为月份:

df1 = (df.groupby(df.index.to_period('m'))
         .head(10)
         .set_index('Symbol', append=True)['Circulating.Supply']
         .unstack())
df1.index = df1.index.to_period('m').rename('month')
#print (df1)

重塑相似并创建带有月份周期的MultiIndex:

df2 = df.set_index('Symbol', append=True)['Price'].unstack()
df2.index = [df2.index, df2.index.to_period('m').rename('month')]
#print (df2)

除以月份,删除辅助级别,重新整形并最后添加新列:

s = df2.div(df1, level=1).reset_index(level=1, drop=True).stack().rename('new')

df = df.join(s, on=['Date','Symbol'])
#print (df)

【讨论】:

  • 效果很好!非常感谢你的帮助。我想知道,如何移动“新”列的值,使其以 2017-01-02 开头?谢谢
  • @rakamakafo - 是的,需要df.set_index(df.index - pd.Timedelta(1, unit='d'))df2 减去一天,检查print (df1)print (df2) 以了解DatetimeIndex 的差异
  • 您的解决方案正在运行,但我正在寻找不同的输出。您的解决方案将当天的供应量乘以第二天的价格。我需要在每个月的第一天记录前 10 个硬币的供应量,然后将其乘以每月每隔一天的价格,直到月底。然后每个月重复这个操作。因此,例如“2017-01-03”上的“新”应该是每月第一天的 BTC 供应乘以“2017-01-03”上的价格,即 1.607734e+07 * 1043.84
  • @rakamakafo - 一个问题 - 您是否需要每天提取 top10,然后在上面的评论中应用解决方案?还是只在当月的第一天获得top10,然后申请解决方案?
  • 非常感谢您抽出宝贵的时间和您的天才解决方案。我只需要将 change div 更改为 mul ,我就得到了所需的输出。再次感谢!
【解决方案2】:

无需进入日期时间索引,这将适用于您提供的数据。请注意,如果超过一个月,您可能需要使用 DateTimeIndex(可能使用.astype('datetime64[M]'))与每个月的第一个进行比较:

s = pd.Series(
         pd.concat([df.loc[pd.to_datetime('2017-01-01')]['Circulating.Supply'] * 
          df.loc[date]['Price'] 
      for date in df.index.get_level_values('Date').unique()])
                    .dropna())
df['New.Cap'] = s.values

【讨论】:

  • 谢谢你的解决方案,但我得到一个 ValueError: 值的长度与索引的长度不匹配。
猜你喜欢
  • 2012-11-18
  • 2016-03-12
  • 2017-07-18
  • 1970-01-01
  • 1970-01-01
  • 2021-12-01
  • 2022-01-01
  • 2021-03-05
  • 2019-01-20
相关资源
最近更新 更多