我有以下pandas数据帧df
:
index A B C
1 1 2 3
2 9 5 4
3 7 12 8
... ... ... ...
我希望每行的最大值保持不变,所有其他值都变为-1
。因此输出如下:
index A B C
1 -1 -1 3
2 9 -1 -1
3 -1 12 -1
... ... ... ...
通过使用df.max(axis = 1)
,我获得了每行最大值的panda Series
。但是,我不确定如何最佳地使用这些最大值来创建我需要的结果。我正在寻找一个矢量化,快速的实现。
答案 0 :(得分:4)
考虑使用where
:
>>> df.where(df.eq(df.max(1), 0), -1)
A B C
index
1 -1 -1 3
2 9 -1 -1
3 -1 12 -1
这里df.eq(df.max(1), 0)
是一个布尔数据框,用于标记行的最大值;真值(最大值)保持不变,而假值变为-1。如果您愿意,也可以使用Series或其他DataFrame而不是标量。
该操作也可以在现场完成(通过传递inplace=True
)。
答案 1 :(得分:2)
您可以按行eq
与max
进行比较,然后应用反向mask
来创建布尔mask
:
print df
A B C
index
1 1 2 3
2 9 5 4
3 7 12 8
print df.max(axis=1)
index
1 3
2 9
3 12
dtype: int64
mask = df.eq(df.max(axis=1), axis=0)
print mask
A B C
index
1 False False True
2 True False False
3 False True False
df[~mask] = -1
print df
A B C
index
1 -1 -1 3
2 9 -1 -1
3 -1 12 -1
所有在一起:
df[~df.eq(df.max(axis=1), axis=0)] = -1
print df
A B C
index
1 -1 -1 3
2 9 -1 -1
3 -1 12 -1
答案 2 :(得分:1)
为每个值创建一个大小为df
的新数据帧,其中包含-1。然后使用enumerate
来获取给定行中的第一个最大值,使用标量的整数获取/设置(iat
)。
df2 = pd.DataFrame(-np.ones(df.shape), columns=df.columns, index=df.index)
for row, col in enumerate(np.argmax(df.values, axis=1)):
df2.iat[row, col] = df.iat[row, col]
>>> df2
0 1 2
0 -1 -1 3
1 9 -1 -1
2 -1 12 -1
<强>计时强>
df = pd.DataFrame(np.random.randn(10000, 10000))
%%timeit
df2 = pd.DataFrame(-np.ones(df.shape))
for row, col in enumerate(np.argmax(df.values, axis=1)):
df2.iat[row, col] = df.iat[row, col]
1 loops, best of 3: 1.19 s per loop
%timeit df.where(df.eq(df.max(1), 0), -1)
1 loops, best of 3: 6.27 s per loop
# Using inplace=True
%timeit df.where(df.eq(df.max(1), 0), -1, inplace=True)
1 loops, best of 3: 5.58 s per loop
%timeit df[~df.eq(df.max(axis=1), axis=0)] = -1
1 loops, best of 3: 5.65 s per loop