Pandas:列和索引之间的多索引应用函数

时间:2016-08-09 22:26:45

标签: python pandas apply attributeerror multi-index

我有一个多索引数据框,如下所示:

In[13]: df
Out[13]:
              Last Trade
Date       Ticker           
1983-03-30 CLM83  1983-05-18
           CLN83  1983-06-17
           CLQ83  1983-07-18
           CLU83  1983-08-19
           CLV83  1983-09-16
           CLX83  1983-10-18
           CLZ83  1983-11-18
1983-04-04 CLM83  1983-05-18
           CLN83  1983-06-17
           CLQ83  1983-07-18
           CLU83  1983-08-19
           CLV83  1983-09-16
           CLX83  1983-10-18
           CLZ83  1983-11-18

索引有两个级别(即' Date'' Ticker')。我想在“最后交易”专栏中应用一个功能。这会让我知道有多少个月将这个' Last Trade'来自索引的日期'日期' 我找到了一个执行计算的函数:

from calendar import monthrange

def monthdelta(d1, d2):
    delta = 0
    while True:
        mdays = monthrange(d1.year, d1.month)[1]
        d1 += datetime.timedelta(days=mdays)
        if d1 <= d2:
            delta += 1
        else:
            break
    return delta

我尝试应用以下函数h,但它返回一个AttributeError:&#39;时间戳&#39;对象没有属性&#39; index&#39;:

In[14]: h = lambda x: monthdelta(x.index.get_level_values(0),x)

In[15]: df['Last Trade'] = df['Last Trade'].apply(h)

如何应用同时使用列和索引值的函数?

感谢您的提示,

2 个答案:

答案 0 :(得分:3)

使用df.index.to_series().str.get(0)获取索引的第一级。

(df['Last Trade'].dt.month - df.index.to_series().str.get(0).dt.month) + \
(df['Last Trade'].dt.year - df.index.to_series().str.get(0).dt.year) * 12

Date        Ticker
1983-03-30  CLM83     2
            CLN83     3
            CLQ83     4
            CLU83     5
            CLV83     6
            CLX83     7
            CLZ83     8
1983-04-04  CLM83     1
            CLN83     2
            CLQ83     3
            CLU83     4
            CLV83     5
            CLX83     6
            CLZ83     7
dtype: int64

时序

鉴于df

enter image description here

<强> pd.concat([df for _ in range(10000)])

enter image description here

答案 1 :(得分:3)

尝试使用此功能代替您的功能:

选项1

您将获得一个整数

def monthdelta(row):
    trade = row['Last Trade'].year*12 + row['Last Trade'].month
    date = row['Date'].year*12 + row['Date'].month
    return trade - date

df.reset_index().apply(monthdelta, axis=1)

受PiRsquared的启发:

df = df.reset_index()
(df['Last Trade'].dt.year*12 + df['Last Trade'].dt.month) -\
(df['Date'].dt.year*12 + df['Date'].dt.month)

选项2

你得到numpy.timedelta64

可以直接用于其他日期计算。但是,这将是几天而不是几个月的形式,因为days in a month are not constant

的数量
def monthdelta(row):
    return row['Last Trade'] - row['Date']

df.reset_index().apply(monthdelta, axis=1)

受PiRsquared的启发:

df = df.reset_index()
df['Last Trade'] - df['Date']

选项2当然会更快,因为它涉及更少的计算。选择你喜欢的!

要获取您的索引:df.index = df[['Date', 'Ticker']]