Pandas: сдвинуть значения на одну строку внутри группы

У меня есть кадр данных Pandas, и я хочу создать новый столбец, значения которого соответствуют другому столбцу, сдвинутому на одну строку. В последней строке должно отображаться NaN.

Уловка заключается в том, что я хочу сделать это по группе, причем последняя строка каждой группы показывает NaN. НЕ иметь последнюю строку группы "украсть" значение из группы, которая оказывается смежной в кадре данных.

Моя попытка реализации довольно позорно нарушена, поэтому я явно недопонимаю что-то фундаментальное.

df['B_shifted'] = df.groupby(['A'])['B'].transform(lambda x:x.values[1:])

Ответ 1

Shift работает с выходом предложения groupby:

>>> df = pandas.DataFrame(numpy.random.randint(1,3, (10,5)), columns=['a','b','c','d','e'])
>>> df
   a  b  c  d  e
0  2  1  2  1  1
1  2  1  1  1  1
2  1  2  2  1  2
3  1  2  1  1  2
4  2  2  1  1  2
5  2  2  2  2  1
6  2  2  1  1  1
7  2  2  2  1  1
8  2  2  2  2  1
9  2  2  2  2  1


for k, v in df.groupby('a'):
    print k
    print 'normal'
    print v
    print 'shifted'
    print v.shift(1)

1
normal
   a  b  c  d  e
2  1  2  2  1  2
3  1  2  1  1  2
shifted
    a   b   c   d   e
2 NaN NaN NaN NaN NaN
3   1   2   2   1   2
2
normal
   a  b  c  d  e
0  2  1  2  1  1
1  2  1  1  1  1
4  2  2  1  1  2
5  2  2  2  2  1
6  2  2  1  1  1
7  2  2  2  1  1
8  2  2  2  2  1
9  2  2  2  2  1
shifted
    a   b   c   d   e
0 NaN NaN NaN NaN NaN
1   2   1   2   1   1
4   2   1   1   1   1
5   2   2   1   1   2
6   2   2   2   2   1
7   2   2   1   1   1
8   2   2   2   1   1
9   2   2   2   2   1

Ответ 2

Новые версии панд теперь могут выполнять shift группы:

df['B_shifted'] = df.groupby(['A'])['B'].shift(1)

Обратите внимание, что при переключении вниз, это первый ряд, который имеет NaN.

Ответ 3

Комментарий @EdChum - лучший ответ на этот вопрос, поэтому я размещаю его здесь для потомков:

df['B_shifted'] = df.groupby(['A'])['B'].transform(lambda x:x.shift())

или аналогичным образом

df['B_shifted'] = df.groupby(['A'])['B'].transform('shift').

Быстрая нотация, конечно, более гибкая (например, если вы хотите сдвинуть на 2).

Ответ 4

Все вышеприведенные ответы делают ошибку:

shift(1) - это смещение вверх на одну строку, что является поведением по умолчанию;
shift(-1) на самом деле о сдвиге вниз на одну строку.

см. пример shift документации панд