[英]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
列中的相同值填充它,但行向上移動一行。 每個user
和date
組組的最后一行也應該被刪除。 在下面的示例中,您可以看到缺少例如值對 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.