pandas:将最后N行多索引设置为Nan,以便使用shift

时间:2015-06-02 00:30:01

标签: python pandas

我正在努力加快我的groupby.apply + shift和 感谢前面的问题和回答:How to speed up Pandas multilevel dataframe shift by group?我可以证明,当你有很多小组时,确实可以加快速度。

从这个问题我现在有以下代码将每个多索引中的第一个条目设置为Nan。现在我可以在全球范围内而不是按组进行。

df.iloc[df.groupby(level=0).size().cumsum()[:-1]] = np.nan

但我想向前看,而不是向后看,需要跨N行进行计算。所以我试图使用一些类似的代码将最后N个条目设置为NaN,但显然我缺少一些重要的索引知识,因为我无法弄明白。

我想要转换它,以便每个条目都是一个范围而不是一个整数。我该怎么做?

 # the start of each group, ignoring the first entry
 df.groupby(level=0).size().cumsum()[1:]

如果您想尝试,请进行测试设置(向后移动):

length = 5
groups = 3
rng1 = pd.date_range('1/1/1990', periods=length, freq='D')
frames = []
for x in xrange(0,groups):
    tmpdf = pd.DataFrame({'date':rng1,'category':int(10000000*abs(np.random.randn())),'colA':np.random.randn(length),'colB':np.random.randn(length)})
    frames.append(tmpdf)
df = pd.concat(frames)

df.sort(columns=['category','date'],inplace=True)
df.set_index(['category','date'],inplace=True,drop=True)
df['tmpShift'] = df['colB'].shift(1)
df.iloc[df.groupby(level=0).size().cumsum()[:-1]] = np.nan

# Yay this is so much faster.
df['newColumn'] = df['tmpShift'] / df['colA']
df.drop('tmp',1,inplace=True)

谢谢!

1 个答案:

答案 0 :(得分:0)

我最终使用groupby应用如下(并编码为向前或向后工作):

def replace_tail(grp,col,N,value):
    if (N > 0):
        grp[col][:N] = value
    else:
        grp[col][N:] = value
    return grp

df = df.groupby(level=0).apply(replace_tail,'tmpShift',2,np.nan)

所以最终的代码是:

def replace_tail(grp,col,N,value):
    if (N > 0):
        grp[col][:N] = value
    else:
        grp[col][N:] = value
    return grp


length = 5
groups = 3
rng1 = pd.date_range('1/1/1990', periods=length, freq='D')
frames = []
for x in xrange(0,groups):
    tmpdf = pd.DataFrame({'date':rng1,'category':int(10000000*abs(np.random.randn())),'colA':np.random.randn(length),'colB':np.random.randn(length)})
    frames.append(tmpdf)
df = pd.concat(frames)

df.sort(columns=['category','date'],inplace=True)
df.set_index(['category','date'],inplace=True,drop=True)
shiftBy=-1
df['tmpShift'] = df['colB'].shift(shiftBy)
df = df.groupby(level=0).apply(replace_tail,'tmpShift',shiftBy,np.nan)

# Yay this is so much faster.
df['newColumn'] = df['tmpShift'] / df['colA']
df.drop('tmpShift',1,inplace=True)