如何从 Python 数据帧中行的前一个密集排名中读取值
How to read a value from the previous dense rank of the row in Python dataframe
我有 table.csv:
ID,X,X_2,X_3,Rank
XJ5,30,24,37,1
XK4,20,22,20,1
XK5,33,27,38,1
XK7,22,19,22,1
XJ5,33,22,21,2
XK4,20,22,22,2
XK5,33,24,29,2
XK6,23,21,22,2
XJ5,24,22,19,3
XK4,21,20,34,3
XK5,19,22,32,3
XK6,44,24,21,3
XK7,32,21,23,3
并希望输出 table:
ID,X,X_2,X_3,Rank,PrevX
XJ5,30,24,37,1,NA
XK4,20,22,20,1,NA
XK5,33,27,38,1,NA
XK7,22,19,22,1,NA
XJ5,33,22,21,2,30
XK4,20,22,22,2,20
XK5,33,24,29,2,33
XK6,23,21,22,2,NA
XJ5,24,22,19,3,33
XK4,21,20,34,3,20
XK5,19,22,32,3,33
XK6,44,24,21,3,23
XK7,32,21,23,3,NA
新的 PrevX 列是 Rank-1 行的 ID 的 X 值
这是我目前的情况:
import pandas
df = pandas.read_csv('table.csv')
更新
一种方法是:
- 使用
groupby
对每个 id
的数据进行分组,对每个组应用以下内容:
rank
使用 sort_values
订购
- 创建一个临时列,其中
rank
使用 shift
移动一位
- 使用
add
添加 1
到这个新列
- 使用
np.where
将此新列与 rank
列进行比较:如果它们相等,则分配先前的 X
值,否则分配 NaN
可选以匹配预期输出:
- 使用
drop
删除无用的列
- 用
reset_index
重置索引
- 使用
sort_values
按 rank
排序。
这里是代码:
def get_previous(df):
df = df.sort_values(by="Rank")
df["rank_shifted"] = df.Rank.shift().add(1)
df["PrevX"] = np.where(df.rank_shifted == df.Rank, df.X.shift(), np.NaN)
return df
df = df.groupby('ID').apply(get_previous)
print(df)
# ID X X_2 X_3 Rank rank_shifted PrevX
# ID
# XJ5 0 XJ5 30 24 37 1 NaN NaN
# 3 XJ5 33 22 21 2 2.0 30.0
# 6 XJ5 24 22 19 3 3.0 33.0
# XK4 1 XK4 20 22 20 1 NaN NaN
# 4 XK4 20 22 22 2 2.0 20.0
# 7 XK4 21 20 34 3 3.0 20.0
# XK5 2 XK5 33 27 38 1 NaN NaN
# 5 XK5 33 24 29 2 2.0 33.0
# 8 XK5 19 22 32 3 3.0 33.0
# Match output
df = df.reset_index(drop=True).sort_values(by="Rank").drop("rank_shifted", axis=1)
print(df)
# ID X X_2 X_3 Rank PrevX
# 0 XJ5 30 24 37 1 NaN
# 3 XK4 20 22 20 1 NaN
# 6 XK5 33 27 38 1 NaN
# 1 XJ5 33 22 21 2 30.0
# 4 XK4 20 22 22 2 20.0
# 7 XK5 33 24 29 2 33.0
# 2 XJ5 24 22 19 3 33.0
# 5 XK4 21 20 34 3 20.0
# 8 XK5 19 22 32 3 33.0
原回答
假设排名总是由 3 行组成,您可以使用 shift
:
df["PrevX"] = df.X.shift(3)
print(df)
# ID X X_2 X_3 Rank PrevX
# 0 XJ5 30 24 37 1 NaN
# 1 XK4 20 22 20 1 NaN
# 2 XK5 33 27 38 1 NaN
# 3 XJ5 33 22 21 2 30.0
# 4 XK4 20 22 22 2 20.0
# 5 XK5 33 24 29 2 33.0
# 6 XJ5 24 22 19 3 33.0
# 7 XK4 21 20 34 3 20.0
# 8 XK5 19 22 32 3 33.0
如果您不知道每个 rank
组的行数,您可以使用 groupby
和 size
找到它:
print(df.groupby('Rank').size())
# Rank
# 1 3
# 2 3
# 3 3
希望对您有所帮助!
我认为groupby
和shift
如下:
_ groupby
在 Rank
上找到 diff
是 1
创建掩码 m
以根据条件 [=] 识别哪个 ID
具有价值14=] 是相邻的 (Rank-1)。 Rank-1 内任何相同的 ID
将被标记为 True
,否则 False
_ groupby
ID
和 shift
X
_ 最后,使用 where
和掩码 m
将 m
中的 False
翻转为 NaN
m = df.groupby('ID').Rank.diff().eq(1)
df['prevX'] = df.groupby('ID').X.shift().where(m)
Out[28]:
ID X X_2 X_3 Rank prevX
0 XJ5 30 24 37 1 NaN
1 XK4 20 22 20 1 NaN
2 XK5 33 27 38 1 NaN
3 XK7 22 19 22 1 NaN
4 XJ5 33 22 21 2 30.0
5 XK4 20 22 22 2 20.0
6 XK5 33 24 29 2 33.0
7 XK6 23 21 22 2 NaN
8 XJ5 24 22 19 3 33.0
9 XK4 21 20 34 3 20.0
10 XK5 19 22 32 3 33.0
11 XK6 44 24 21 3 23.0
12 XK7 32 21 23 3 NaN
我有 table.csv:
ID,X,X_2,X_3,Rank
XJ5,30,24,37,1
XK4,20,22,20,1
XK5,33,27,38,1
XK7,22,19,22,1
XJ5,33,22,21,2
XK4,20,22,22,2
XK5,33,24,29,2
XK6,23,21,22,2
XJ5,24,22,19,3
XK4,21,20,34,3
XK5,19,22,32,3
XK6,44,24,21,3
XK7,32,21,23,3
并希望输出 table:
ID,X,X_2,X_3,Rank,PrevX
XJ5,30,24,37,1,NA
XK4,20,22,20,1,NA
XK5,33,27,38,1,NA
XK7,22,19,22,1,NA
XJ5,33,22,21,2,30
XK4,20,22,22,2,20
XK5,33,24,29,2,33
XK6,23,21,22,2,NA
XJ5,24,22,19,3,33
XK4,21,20,34,3,20
XK5,19,22,32,3,33
XK6,44,24,21,3,23
XK7,32,21,23,3,NA
新的 PrevX 列是 Rank-1 行的 ID 的 X 值
这是我目前的情况:
import pandas
df = pandas.read_csv('table.csv')
更新
一种方法是:
- 使用
groupby
对每个id
的数据进行分组,对每个组应用以下内容: rank
使用sort_values
订购
- 创建一个临时列,其中
rank
使用shift
移动一位
- 使用
add
添加 - 使用
np.where
将此新列与rank
列进行比较:如果它们相等,则分配先前的X
值,否则分配NaN
可选以匹配预期输出:
- 使用
drop
删除无用的列
- 用
reset_index
重置索引
- 使用
sort_values
按rank
排序。
- 使用
1
到这个新列
这里是代码:
def get_previous(df):
df = df.sort_values(by="Rank")
df["rank_shifted"] = df.Rank.shift().add(1)
df["PrevX"] = np.where(df.rank_shifted == df.Rank, df.X.shift(), np.NaN)
return df
df = df.groupby('ID').apply(get_previous)
print(df)
# ID X X_2 X_3 Rank rank_shifted PrevX
# ID
# XJ5 0 XJ5 30 24 37 1 NaN NaN
# 3 XJ5 33 22 21 2 2.0 30.0
# 6 XJ5 24 22 19 3 3.0 33.0
# XK4 1 XK4 20 22 20 1 NaN NaN
# 4 XK4 20 22 22 2 2.0 20.0
# 7 XK4 21 20 34 3 3.0 20.0
# XK5 2 XK5 33 27 38 1 NaN NaN
# 5 XK5 33 24 29 2 2.0 33.0
# 8 XK5 19 22 32 3 3.0 33.0
# Match output
df = df.reset_index(drop=True).sort_values(by="Rank").drop("rank_shifted", axis=1)
print(df)
# ID X X_2 X_3 Rank PrevX
# 0 XJ5 30 24 37 1 NaN
# 3 XK4 20 22 20 1 NaN
# 6 XK5 33 27 38 1 NaN
# 1 XJ5 33 22 21 2 30.0
# 4 XK4 20 22 22 2 20.0
# 7 XK5 33 24 29 2 33.0
# 2 XJ5 24 22 19 3 33.0
# 5 XK4 21 20 34 3 20.0
# 8 XK5 19 22 32 3 33.0
原回答
假设排名总是由 3 行组成,您可以使用 shift
:
df["PrevX"] = df.X.shift(3)
print(df)
# ID X X_2 X_3 Rank PrevX
# 0 XJ5 30 24 37 1 NaN
# 1 XK4 20 22 20 1 NaN
# 2 XK5 33 27 38 1 NaN
# 3 XJ5 33 22 21 2 30.0
# 4 XK4 20 22 22 2 20.0
# 5 XK5 33 24 29 2 33.0
# 6 XJ5 24 22 19 3 33.0
# 7 XK4 21 20 34 3 20.0
# 8 XK5 19 22 32 3 33.0
如果您不知道每个 rank
组的行数,您可以使用 groupby
和 size
找到它:
print(df.groupby('Rank').size())
# Rank
# 1 3
# 2 3
# 3 3
希望对您有所帮助!
我认为groupby
和shift
如下:
_ groupby
在 Rank
上找到 diff
是 1
创建掩码 m
以根据条件 [=] 识别哪个 ID
具有价值14=] 是相邻的 (Rank-1)。 Rank-1 内任何相同的 ID
将被标记为 True
,否则 False
_ groupby
ID
和 shift
X
_ 最后,使用 where
和掩码 m
将 m
中的 False
翻转为 NaN
m = df.groupby('ID').Rank.diff().eq(1)
df['prevX'] = df.groupby('ID').X.shift().where(m)
Out[28]:
ID X X_2 X_3 Rank prevX
0 XJ5 30 24 37 1 NaN
1 XK4 20 22 20 1 NaN
2 XK5 33 27 38 1 NaN
3 XK7 22 19 22 1 NaN
4 XJ5 33 22 21 2 30.0
5 XK4 20 22 22 2 20.0
6 XK5 33 24 29 2 33.0
7 XK6 23 21 22 2 NaN
8 XJ5 24 22 19 3 33.0
9 XK4 21 20 34 3 20.0
10 XK5 19 22 32 3 33.0
11 XK6 44 24 21 3 23.0
12 XK7 32 21 23 3 NaN