AVL*_*AVL 1 python pandas dummy-variable
我有一个像这样构建的数据库:
>>> df = pd.DataFrame({'id':[1,1,1,2,2,2,2,3,4],'value':[1,2,3,1,2,3,4,1,1]})
>>> df
id value
0 1 1
1 1 2
2 1 3
3 2 1
4 2 2
5 2 3
6 2 4
7 3 1
8 4 1
Run Code Online (Sandbox Code Playgroud)
并且我想为每个 ID 的第 n 个最大值生成一个虚拟变量(此处为 n = 2),以便对于所有第 n 个最大值之一的值等于 1:
id value Largest
0 1 1 0
1 1 2 1
2 1 3 1
3 2 1 0
4 2 2 0
5 2 3 1
6 2 4 1
7 3 1 1
8 4 1 1
Run Code Online (Sandbox Code Playgroud)
我试过了:
df['highest'] = 0
df['highest'].loc[df['value'].isin(df.groupby(['id'])['value'].nlargest(1))] = 1
Run Code Online (Sandbox Code Playgroud)
但是如果某个 ID 的值恰好是另一个 ID 中的最高值,那将会错误地分配值
设置
df = pd.DataFrame({'id':[1,1,1,2,2,2,2,3,4],'value':[1,2,3,1,2,3,4,1,1]})
n = 2
Run Code Online (Sandbox Code Playgroud)
nlargest和loc:df['flag'] = 0
df.loc[df.groupby('id').value.nlargest(n).index.get_level_values(1), 'flag'] = 1
Run Code Online (Sandbox Code Playgroud)
np.where和assign:这避免了修改 DataFrame 就地。
df.assign(
flag=np.where(
df.index.isin(df.groupby('id').value.nlargest(n).index.get_level_values(1)), 1, 0
)
)
Run Code Online (Sandbox Code Playgroud)
两者都会导致:
id value flag
0 1 1 0
1 1 2 1
2 1 3 1
3 2 1 0
4 2 2 0
5 2 3 1
6 2 4 1
7 3 1 1
8 4 1 1
Run Code Online (Sandbox Code Playgroud)
正如@jezrael 所指出的,np.where这里并不是真的有必要,因为您正在寻找二进制结果,您可以改为使用:
df.assign(flag=df.index.isin(df.groupby('id').value.nlargest(n).index.get_level_values(1)).astype(int))
Run Code Online (Sandbox Code Playgroud)