假设我有一个包含3列的数据框:Date,Ticker,Value(没有索引,至少可以开始).我有很多日期和许多代码,但每个(ticker, date)
元组都是独一无二的.(但显然相同的日期会出现在很多行中,因为它会存在多个代码,并且同一个代码将显示在多行中,因为它将存在很多日期.)
最初,我的行按特定顺序排列,但未按任何列排序.
我想计算每个股票代码的第一个差异(每日更改)(按日期排序),并将它们放在我的数据框中的新列中.鉴于这种背景,我不能简单地这样做
df['diffs'] = df['value'].diff()
因为相邻的行不是来自同一个自动收报机.排序如下:
df = df.sort(['ticker', 'date']) df['diffs'] = df['value'].diff()
没有解决问题,因为会有"边界".即在那之后,一个股票代码的最后一个值将高于下一个股票代码的第一个值.然后计算差异会使两个代码之间产生差异.我不想要这个.我希望每个自动收报机的最早日期NaN
在其差异列中结束.
这似乎是一个明显的使用时间,groupby
但无论出于何种原因,我似乎无法让它正常工作.为了清楚起见,我想执行以下过程:
根据它们对行进行分组 ticker
在每个组中,按行分类 date
在每个已排序的组中,计算value
列的差异
将这些差异放入新diffs
列中的原始数据框中(理想情况下,保留原始数据框顺序).
我不得不想象这是一个单行.但是我错过了什么?
编辑于2013-12-17的晚上9点
好的...一些进展.我可以执行以下操作来获取新的数据帧:
result = df.set_index(['ticker', 'date'])\ .groupby(level='ticker')\ .transform(lambda x: x.sort_index().diff())\ .reset_index()
但是,如果我理解groupby的机制,我的行现在将首先排序ticker
,然后排序date
.那是对的吗?如果是这样,我是否需要进行合并以附加差异列(当前位于result['current']
原始数据框中df
?
做你自己描述的事情并不容易
df.sort(['ticker', 'date'], inplace=True) df['diffs'] = df['value'].diff()
然后更正边框:
mask = df.ticker != df.ticker.shift(1) df['diffs'][mask] = np.nan
保持你可能idx = df.index
在开始时做的原始索引,然后在最后你可以做df.reindex(idx)
,或者如果它是一个巨大的数据帧,执行操作
df.filter(['ticker', 'date', 'value'])
然后join
是最后的两个数据帧.
编辑:或者,(虽然仍未使用groupby
)
df.set_index(['ticker','date'], inplace=True) df.sort_index(inplace=True) df['diffs'] = np.nan for idx in df.index.levels[0]: df.diffs[idx] = df.value[idx].diff()
对于
date ticker value 0 63 C 1.65 1 88 C -1.93 2 22 C -1.29 3 76 A -0.79 4 72 B -1.24 5 34 A -0.23 6 92 B 2.43 7 22 A 0.55 8 32 A -2.50 9 59 B -1.01
这将产生:
value diffs ticker date A 22 0.55 NaN 32 -2.50 -3.05 34 -0.23 2.27 76 -0.79 -0.56 B 59 -1.01 NaN 72 -1.24 -0.23 92 2.43 3.67 C 22 -1.29 NaN 63 1.65 2.94 88 -1.93 -3.58
好.很多人都在考虑这个问题,我认为这是我最喜欢的上述解决方案和一些游戏的组合.原始数据存在于df
:
df.sort(['ticker', 'date'], inplace=True) # for this example, with diff, I think this syntax is a bit clunky # but for more general examples, this should be good. But can we do better? df['diffs'] = df.groupby(['ticker'])['value'].transform(lambda x: x.diff()) df.sort_index(inplace=True)
这将完成我想要的一切.而我真正喜欢的是它可以推广到你想要应用比复杂更复杂的函数的情况diff
.特别是,您可以做一些事情,比如lambda x: pd.rolling_mean(x, 20, 20)
制作一个滚动方式的列,您不必担心每个自动收报机的数据被任何其他自动收报机的数据损坏(groupby
为您处理...).
所以这是我留下的问题......为什么下面的工作不适用于开始的行df['diffs']
:
df['diffs'] = df.groupby[('ticker')]['value'].transform(np.diff)
当我这样做时,我得到一个diffs
满是0的列.有什么想法吗?