首页
学习
活动
专区
工具
TVP
发布
社区首页 >问答首页 >使用groupby后在Pandas中计算np.diff导致意外结果

使用groupby后在Pandas中计算np.diff导致意外结果
EN

Stack Overflow用户
提问于 2013-12-19 07:34:19
回答 2查看 18.4K关注 0票数 35

我已经得到了一个数据帧,并且我正在尝试向它追加一列顺序差异。我找到了一个我很喜欢的方法(并且很好地概括了我的用例)。但我注意到了一件奇怪的事情。你能帮我弄明白吗?

以下是一些具有正确结构的数据(基于答案here建模的代码):

代码语言:javascript
复制
import pandas as pd
import numpy as np
import random
from itertools import product

random.seed(1)       # so you can play along at home
np.random.seed(2)    # ditto

# make a list of dates for a few periods
dates = pd.date_range(start='2013-10-01', periods=4).to_native_types()
# make a list of tickers
tickers = ['ticker_%d' % i for i in range(3)]
# make a list of all the possible (date, ticker) tuples
pairs = list(product(dates, tickers))
# put them in a random order
random.shuffle(pairs)
# exclude a few possible pairs
pairs = pairs[:-3]
# make some data for all of our selected (date, ticker) tuples
values = np.random.rand(len(pairs))

mydates, mytickers = zip(*pairs)
data = pd.DataFrame({'date': mydates, 'ticker': mytickers, 'value':values})

好的,很好。这给了我一个框架,如下所示:

代码语言:javascript
复制
     date        ticker      value
0    2013-10-03  ticker_2    0.435995
1    2013-10-04  ticker_2    0.025926
2    2013-10-02  ticker_1    0.549662
3    2013-10-01  ticker_0    0.435322
4    2013-10-02  ticker_2    0.420368
5    2013-10-03  ticker_0    0.330335
6    2013-10-04  ticker_1    0.204649
7    2013-10-02  ticker_0    0.619271
8    2013-10-01  ticker_2    0.299655

我的目标是向这个数据框架中添加一个包含顺序更改的新列。为了做到这一点,数据需要是正确的,但排序和差异需要“以节拍为单位”进行,以便另一个节拍中的间隙不会导致给定节拍的NA。我希望在不以任何其他方式干扰数据帧的情况下完成此操作(即,我不希望根据执行差分所需的内容对结果dataframe进行重新排序)。下面的代码可以工作:

代码语言:javascript
复制
data1 = data.copy() #let's leave the original data alone for later experiments
data1.sort(['ticker', 'date'], inplace=True)
data1['diffs'] = data1.groupby(['ticker'])['value'].transform(lambda x: x.diff())
data1.sort_index(inplace=True)
data1

并返回:

代码语言:javascript
复制
     date        ticker      value       diffs
0    2013-10-03  ticker_2    0.435995    0.015627
1    2013-10-04  ticker_2    0.025926   -0.410069
2    2013-10-02  ticker_1    0.549662    NaN
3    2013-10-01  ticker_0    0.435322    NaN
4    2013-10-02  ticker_2    0.420368    0.120713
5    2013-10-03  ticker_0    0.330335   -0.288936
6    2013-10-04  ticker_1    0.204649   -0.345014
7    2013-10-02  ticker_0    0.619271    0.183949
8    2013-10-01  ticker_2    0.299655    NaN

到现在为止还好。如果我用这里显示的更简洁的代码替换上面的中间行,一切仍然有效:

代码语言:javascript
复制
data2 = data.copy()
data2.sort(['ticker', 'date'], inplace=True)
data2['diffs'] = data2.groupby('ticker')['value'].diff()
data2.sort_index(inplace=True)
data2

快速检查一下就会发现,实际上,data1等于data2。但是,如果我这样做:

代码语言:javascript
复制
data3 = data.copy()
data3.sort(['ticker', 'date'], inplace=True)
data3['diffs'] = data3.groupby('ticker')['value'].transform(np.diff)
data3.sort_index(inplace=True)
data3

我得到了一个奇怪的结果:

代码语言:javascript
复制
     date        ticker     value       diffs
0    2013-10-03  ticker_2    0.435995    0
1    2013-10-04  ticker_2    0.025926   NaN
2    2013-10-02  ticker_1    0.549662   NaN
3    2013-10-01  ticker_0    0.435322   NaN
4    2013-10-02  ticker_2    0.420368   NaN
5    2013-10-03  ticker_0    0.330335    0
6    2013-10-04  ticker_1    0.204649   NaN
7    2013-10-02  ticker_0    0.619271   NaN
8    2013-10-01  ticker_2    0.299655    0

这里发生了什么事?当您在Pandas对象上调用.diff方法时,它不只是调用np.diff吗?我知道在DataFrame类上有一个diff方法,但是如果没有我用来使data1工作的lambda函数语法,我不知道如何将它传递给transform。我是不是遗漏了什么?为什么data3中的diffs列是扭曲的?我如何在transform中调用Pandas diff方法,而不需要编写lambda来执行此操作?

EN

回答 2

Stack Overflow用户

回答已采纳

发布于 2013-12-19 08:00:36

很好很容易复制的例子!!更多问题应该是这样的!

只需传递一个lambda来进行转换(这等同于直接传递一个函数对象,例如np.diff (或Series.diff)。因此,这相当于data1/data2

代码语言:javascript
复制
In [32]: data3['diffs'] = data3.groupby('ticker')['value'].transform(Series.diff)

In [34]: data3.sort_index(inplace=True)

In [25]: data3
Out[25]: 
         date    ticker     value     diffs
0  2013-10-03  ticker_2  0.435995  0.015627
1  2013-10-04  ticker_2  0.025926 -0.410069
2  2013-10-02  ticker_1  0.549662       NaN
3  2013-10-01  ticker_0  0.435322       NaN
4  2013-10-02  ticker_2  0.420368  0.120713
5  2013-10-03  ticker_0  0.330335 -0.288936
6  2013-10-04  ticker_1  0.204649 -0.345014
7  2013-10-02  ticker_0  0.619271  0.183949
8  2013-10-01  ticker_2  0.299655       NaN

[9 rows x 4 columns]

我认为np.diff没有遵循numpy自己的unfunc准则来处理数组输入(因此它尝试了各种方法来强制输入和发送输出,例如__array__ on input __array_wrap__ on output)。我不太确定为什么,请看更多的信息here。所以底线是np.diff没有正确地处理索引并进行自己的计算(在这种情况下这是错误的)。

Pandas有很多方法,它们不只是调用numpy函数,主要是因为它们处理不同的数据类型,处理nans,在这种情况下,处理“特殊的”差异。例如,你可以将一个时间频率传递给一个类日期的索引,在那里它会计算出有多少n实际不同。

票数 35
EN

Stack Overflow用户

发布于 2013-12-19 08:01:24

您可以看到,系列.diff()方法与np.diff()不同

代码语言:javascript
复制
In [11]: data.value.diff()  # Note the NaN
Out[11]: 
0         NaN
1   -0.410069
2    0.523736
3   -0.114340
4   -0.014955
5   -0.090033
6   -0.125686
7    0.414622
8   -0.319616
Name: value, dtype: float64

In [12]: np.diff(data.value.values)  # the values array of the column
Out[12]: 
array([-0.41006867,  0.52373625, -0.11434009, -0.01495459, -0.09003298,
       -0.12568619,  0.41462233, -0.31961629])

In [13]: np.diff(data.value) # on the column (Series)
Out[13]: 
0   NaN
1     0
2     0
3     0
4     0
5     0
6     0
7     0
8   NaN
Name: value, dtype: float64

In [14]: np.diff(data.value.index)  # er... on the index
Out[14]: Int64Index([8], dtype=int64)

In [15]: np.diff(data.value.index.values)
Out[15]: array([1, 1, 1, 1, 1, 1, 1, 1])
票数 7
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/20670726

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档