Python-按列保留第一个唯一值

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,

我有一个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,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