Python-按列保留第一个唯一值
我有一个dataframe,它有多个列来表示某个东西是否存在,但它们本质上是有序的。有些东西可能存在于所有3个类别中,但我只想指出它存在于其中的最高级别 因此,对于给定的行,我只需要一个“1”值,但我希望它保持在找到它时的最高级别 对于此行:Python-按列保留第一个唯一值,python,pandas,numpy,Python,Pandas,Numpy,我有一个dataframe,它有多个列来表示某个东西是否存在,但它们本质上是有序的。有些东西可能存在于所有3个类别中,但我只想指出它存在于其中的最高级别 因此,对于给定的行,我只需要一个“1”值,但我希望它保持在找到它时的最高级别 对于此行: 1,1,0,我希望将行更改为1,0,0 这一行: 0,1,1,我希望将行更改为0,1,0 以下是数据的外观示例和预期输出: import pandas as pd #input data df = pd.DataFrame({'id':[1,2,3,4,
1,1,0
,我希望将行更改为1,0,0
这一行:
0,1,1
,我希望将行更改为0,1,0
以下是数据的外观示例和预期输出:
import pandas as pd
#input data
df = pd.DataFrame({'id':[1,2,3,4,5],
'level1':[0,0,0,0,1],
'level2':[1,0,1,0,1],
'level3':[0,1,1,1,0]})
#expected output:
new_df = pd.DataFrame({'id':[1,2,3,4,5],
'level1':[0,0,0,0,1],
'level2':[1,0,1,0,0],
'level3':[0,1,0,1,0]})
使用numpy.zero
并通过numpy.argmax
填充:
将广播
与argmax
一起使用:
两者都产生:
id level1 level2 level3
0 1 0 1 0
1 2 0 0 1
2 3 0 1 0
3 4 0 0 1
4 5 1 0 0
您可以将高级索引与NumPy一起使用。更新底层NumPy数组在这里起作用,因为您的数据帧是
int
dtype
idx = df.iloc[:, 1:].eq(1).values.argmax(1)
df.iloc[:, 1:] = 0
df.values[np.arange(df.shape[0]), idx+1] = 1
print(df)
id level1 level2 level3
0 1 0 1 0
1 2 0 0 1
2 3 0 1 0
3 4 0 0 1
4 5 1 0 0
numpy.eye
cumsum
和mask
通过为最大索引指定1,可以使用
get\u dummies()
df[df.filter(like='level').columns] = pd.get_dummies(df.filter(like='level').idxmax(1))
id level1 level2 level3
0 1 0 1 0
1 2 0 0 1
2 3 0 1 0
3 4 0 0 1
4 5 1 0 0
这个问题有很多好答案。这一个需要最少的代码,并且非常容易理解。
idx = df.iloc[:, 1:].eq(1).values.argmax(1)
df.iloc[:, 1:] = 0
df.values[np.arange(df.shape[0]), idx+1] = 1
print(df)
id level1 level2 level3
0 1 0 1 0
1 2 0 0 1
2 3 0 1 0
3 4 0 0 1
4 5 1 0 0
v = df.iloc[:, 1:].values
i = np.eye(3, dtype=np.int64)
a = v.argmax(1)
df.iloc[:, 1:] = i[a]
df
id level1 level2 level3
0 1 0 1 0
1 2 0 0 1
2 3 0 1 0
3 4 0 0 1
4 5 1 0 0
df.set_index('id').pipe(
lambda d: d.mask(d.cumsum(1) > 1, 0)
).reset_index()
id level1 level2 level3
0 1 0 1 0
1 2 0 0 1
2 3 0 1 0
3 4 0 0 1
4 5 1 0 0
df[df.filter(like='level').columns] = pd.get_dummies(df.filter(like='level').idxmax(1))
id level1 level2 level3
0 1 0 1 0
1 2 0 0 1
2 3 0 1 0
3 4 0 0 1
4 5 1 0 0