簡體   English   中英

將 pandas dataframe 中的值垂直移動一行

[英]Shift values in pandas dataframe vertically by one row

我有一個看起來像這樣的 pandas dataframe

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, 21, 22, 23], 
     'user': ['A', 'A', 'A', 'A', 'A', 'A', 'A', 'A', 'B', 'B', 'B', 'B', 'C', 'C', 'C', 'C', 'C', 'C', 'C', 'C', 'A', 'A', 'A'],
     'date': ['2010-03-02', '2010-03-02', '2010-03-02', '2010-03-02', '2010-03-02', '2010-03-02', '2010-03-02', '2010-03-02', '2010-03-02', '2010-03-02', '2010-03-02', '2010-03-02', '2010-03-02', '2010-03-02', '2010-03-02', '2010-03-02', '2010-03-02', '2010-03-02', '2010-03-02', '2010-03-02', '2010-03-03', '2010-03-03', '2010-03-03']}
df = pd.DataFrame(data=d)
df

value   user    date
1       A       2010-03-02
2       A       2010-03-02
3       A       2010-03-02
4       A       2010-03-02
5       A       2010-03-02
6       A       2010-03-02
7       A       2010-03-02
8       A       2010-03-02
9       B       2010-03-02
10      B       2010-03-02
11      B       2010-03-02
12      B       2010-03-02
13      C       2010-03-02
14      C       2010-03-02
15      C       2010-03-02
16      C       2010-03-02
17      C       2010-03-02
18      C       2010-03-02
19      C       2010-03-02
20      C       2010-03-02
21      A       2010-03-03 
22      A       2010-03-03
23      A       2010-03-03

我想為此 dataframe 創建一個名為value2的新列,用value列中的相同值填充它,但行向上移動一行。 每個userdate組組的最后一行也應該被刪除。 在下面的示例中,您可以看到缺少例如值對 8-9、12-13 和 20-21。

value   user    date        value2
1       A      2010-03-02   2
2       A      2010-03-02   3
3       A      2010-03-02   4
4       A      2010-03-02   5
5       A      2010-03-02   6
6       A      2010-03-02   7
7       A      2010-03-02   8
9       B      2010-03-02   10
10      B      2010-03-02   11
11      B      2010-03-02   12
13      C      2010-03-02   14
14      C      2010-03-02   15
15      C      2010-03-02   16
16      C      2010-03-02   17
17      C      2010-03-02   18
18      C      2010-03-02   19
19      C      2010-03-02   20
21      A      2010-03-02   22
22      A      2010-03-02   23

使用下面的代碼,我幾乎可以得到想要的結果,除了它還生成以下行:

df['value2'] = df.groupby(['user', 'date'])['value'].shift(-1, fill_value=-1)
df = df[df['value2'].ne(-1)]
df

value    user   date         value2
8       A      2010-03-02   21

此外,在更大的數據集上運行此代碼時,它會返回ValueError: cannot reindex from a duplicate axis 任何想法如何解決這兩個問題?

您可以嘗試以下操作,請注意,您的 output 稍后會重復A ,但您的輸入(代碼)沒有,因此可能會造成混淆。

out = (df.assign(next_node=
      df.groupby([df['user'].ne(df['user'].shift()).cumsum(),'date'])['node'].shift(-1))
     .dropna(subset=['next_node']))

print(out.reset_index(drop=True))

    node user        date  next_node
0      1    A  2010-03-02        2.0
1      2    A  2010-03-02        3.0
2      3    A  2010-03-02        4.0
3      4    A  2010-03-02        5.0
4      5    A  2010-03-02        6.0
5      6    A  2010-03-02        7.0
6      7    A  2010-03-02        8.0
7      9    B  2010-03-02       10.0
8     10    B  2010-03-02       11.0
9     11    B  2010-03-02       12.0
10    13    C  2010-03-02       14.0
11    14    C  2010-03-02       15.0
12    15    C  2010-03-02       16.0
13    16    C  2010-03-02       17.0
14    17    C  2010-03-02       18.0
15    18    C  2010-03-02       19.0
16    19    C  2010-03-02       20.0
17    21    A  2010-03-02       22.0
18    22    A  2010-03-02       23.0

這樣的事情應該是最簡單的方法:

df['next_node'] = df['node'] + 1
df = df.loc[df['user'] == df['user'].shift(-1)]

但是,如果df['node']值不是示例中的連續整數,那么您必須這樣做:

df['next_node'] = df['node'].shift(-1)
df = df.loc[df['user'] == df['user'].shift(-1)]
df = df.astype({'next_node': int})

額外步驟的原因是 shift 方法將系列的類型從 int 轉換為 float,因為它必須在末尾添加一個np.nan ,它是一個 float 值。

我認為您的心理 model 誤導了您。 與其將其視為“移動”行,不如將其視為根據下面行中的值計算值。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM