【发布时间】:2019-11-14 08:30:52
【问题描述】:
我有一个数据框,我正在尝试向它附加一列顺序差异。我找到了一种我非常喜欢的方法(并且可以很好地概括我的用例)。但是一路上我注意到一件奇怪的事情。你能帮我理解一下吗?
以下是一些具有正确结构的数据(代码以here 的答案为模型):
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})
好的,太好了。这给了我一个像这样的框架:
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。我想在不以任何其他方式干扰数据帧的情况下做到这一点(即,我不希望根据进行差异所需的内容对结果数据帧进行重新排序)。以下代码有效:
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
然后返回:
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
到目前为止,一切都很好。如果我用这里显示的更简洁的代码替换上面的中间行,一切仍然有效:
data2 = data.copy()
data2.sort(['ticker', 'date'], inplace=True)
data2['diffs'] = data2.groupby('ticker')['value'].diff()
data2.sort_index(inplace=True)
data2
快速检查表明,实际上data1 等于data2。但是,如果我这样做:
data3 = data.copy()
data3.sort(['ticker', 'date'], inplace=True)
data3['diffs'] = data3.groupby('ticker')['value'].transform(np.diff)
data3.sort_index(inplace=True)
data3
我得到一个奇怪的结果:
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 来执行它?
【问题讨论】:
-
请将
sort=False标志添加到 .groupby() 中。你在给我压力。出于某种原因,带有 .diff 的 .groupby 会使用大量内存,而且效率很低,并且在其中添加不必要的排序只会让情况变得更糟。 -
您的问题是关于
np.diff而不是pandas.diff。为您编辑了标题。