pandas 基于条件高效替换panda Dataframe 每行中的值

rggaifut  于 2023-02-14  发布在  其他
关注(0)|答案(3)|浏览(171)

我想用Pandas数据框来得到一个奇怪但又想要的输出数据框。对于每一行,我想用一个空字符串('')替换任何值0.0,用索引值替换所有值1.0。一行上的任何给定值只能是1.0或0.0。
以下是一些示例数据:

# starting df
df = pd.DataFrame.from_dict({'A':[1.0,0.0,0.0],'B':[1.0,1.0,0.0],'C':[0.0,1.0,1.0]})
df.index=['x','y','z']
print(df)

输入df看起来像什么:

A    B    C
x  1.0  1.0  0.0
y  0.0  1.0  1.0
z  0.0  0.0  1.0

我希望输出df看起来像什么:

A  B  C
x  x  x   
y     y  y
z        z

到目前为止,我已经得到了这段效率很低但看起来可以工作的代码:

for idx in df.index:
    df.loc[idx] = df.loc[idx].map(str).replace('1.0',str(idx))
    df.loc[idx] = df.loc[idx].map(str).replace('0.0','')

有谁能建议一个有效的方法来完成这个任务吗?我将使用的实际数据框的形状是(4548,2044),如果这有帮助的话。而且,每次我需要运行这段代码时,列标题和索引值都会不同。
谢谢!

2ledvvac

2ledvvac1#

使用numpy.where,将广播索引转换为numpy数组:

df = pd.DataFrame(np.where(df.eq(1), 
                           df.index.to_numpy()[:, None], 
                           ''),
                   index = df.index, 
                   columns = df.columns)

print(df)
   A  B  C
x  x  x   
y     y  y
z        z

性能(数据大小(4548,2044)):

np.random.seed(2023)
df = pd.DataFrame(np.random.choice([0.0,1.0], size=(4548,2044))).add_prefix('c')
df.index = df.index.astype(str) + 'r'
# print (df)

In [87]: %timeit df.eq(1).mul(df.index, axis=0)
684 ms ± 36.6 ms per loop (mean ± std. dev. of 7 runs, 1 loop each)

In [90]: %timeit pd.DataFrame(np.where(df.eq(1),df.index.to_numpy()[:, None],''),index = df.index, columns = df.columns)
449 ms ± 26.6 ms per loop (mean ± std. dev. of 7 runs, 1 loop each)
368yc8dk

368yc8dk2#

您可以简单地执行以下操作:

for idx, row in df.iterrows():
    df.loc[idx] = ['' if val == 0 else idx for val in row]

其给出:

A  B  C
x  x  x   
y     y  y
z        z
3b6akqbq

3b6akqbq3#

利用1*'x' -> 'x'0*'x' -> ''的以下特性:

out = df.eq(1).mul(df.index, axis=0)
  • 注意:eq(1)将浮点数转换为布尔值,因为True等效于1。如果只有0./1.,也可以使用astype(int)。*

输出:

A  B  C
x  x  x   
y     y  y
z        z

相关问题