垂直移动 pandas 数据框中的值

Shift values in pandas dataframe vertically

我有一个 pandas 数据框,如下所示:

import pandas as pd
d = {'value': [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20], 'user': ['A', 'A', 'A', 'A', 'A', 'A', 'A', 'A', 'B', 'B', 'B', 'B', 'C', 'C', 'C', 'C', 'C', 'C', 'C', 'C',]}
df = pd.DataFrame(data=d)
df

    value   user
    1       A
    2       A
    3       A
    4       A
    5       A
    6       A
    7       A
    8       A
    9       B
    10      B
    11      B
    12      B
    13      C
    14      C
    15      C
    16      C
    17      C
    18      C
    19      C
    20      C

我想为此数据框创建一个名为 value2 的新列,用 value 列中的相同值填充它,但行向上移动一行。每个 user 组的最后一行也应该被删除。在下面的示例中,您可以看到例如缺少值对 8-9

    value  value2      user
    1      2           A
    2      3           A
    3      4           A
    4      5           A
    5      6           A
    6      7           A
    7      8           A
    9      10          B
    10     11          B
    11     12          B
    13     14          C
    14     15          C
    15     16          C
    16     17          C
    17     18          C
    18     19          C
    19     20          C

我知道可以使用 pandas' shift() 函数移动行,但它仍然没有给我所需的输出,如下所示。解决方案似乎是删除每个 user 组的最后一行......并更改列的顺序(用户列应该是第三列)。有什么改进方法吗?

df['value2'] = df['value'].shift(-1, fill_value=0)
df


    value   user    value2
    1       A       2
    2       A       3
    3       A       4
    4       A       5
    5       A       6
    6       A       7
    7       A       8
    8       A       9
    9       B       10
    10      B       11
    11      B       12
    12      B       13
    13      C       14
    14      C       15
    15      C       16
    16      C       17
    17      C       18
    18      C       19
    19      C       20
    20      C       0

使用 DataFrameGroupBy.shift 并删除 -1 行:

df['next_node'] = df.groupby('user')['node'].shift(-1, fill_value=-1)

df = df[df['next_node'].ne(-1)]
print (df)
    node user  next_node
0      1    A          2
1      2    A          3
2      3    A          4
3      4    A          5
4      5    A          6
5      6    A          7
6      7    A          8
8      9    B         10
9     10    B         11
10    11    B         12
12    13    C         14
13    14    C         15
14    15    C         16
15    16    C         17
16    17    C         18
17    18    C         19
18    19    C         20

或通过 userSeries.duplicated 中删除最后一行:

df['next_node'] = df.groupby('user')['node'].shift(-1, fill_value=-1)

df = df[df['user'].duplicated(keep='last')]