У меня есть dataframe, и я пытаюсь добавить столбец последовательных различий к нему. Я нашел метод, который мне очень нравится (и хорошо обобщается для моего варианта использования). Но я заметил одну странную вещь. Можете ли вы помочь мне разобраться в этом?
Вот некоторые данные, которые имеют правильную структуру (код, смоделированный по answer здесь):
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 для данного тикера. Я хочу сделать это, не нарушая структуру данных каким-либо другим способом (т.е. Я не хочу, чтобы результирующий DataFrame был переупорядочен на основе того, что было необходимо для разграничения). Работает следующий код:
data1 = data.copy() #let 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
Что здесь происходит? Когда вы вызываете метод .diff
для объекта Pandas, это не просто вызов np.diff
? Я знаю, что в классе DataFrame
есть метод diff
, но я не мог понять, как передать это значение в transform
без синтаксиса функции lambda
, который я использовал для создания data1
. Я что-то упускаю? Почему столбец diffs
в data3
вялый? Как я могу вызвать метод Pandas diff
в transform
без необходимости писать lambda
для этого?