当为true时,Pandas将布尔列转换为列名

时间:2019-10-14 09:50:34

标签: python pandas

我有一个带布尔值的df(整数值可以是0或1,但是现在不重要):

A B C D
0 0 1 0
1 0 0 0
0 1 1 1
1 0 0 1

我想对其进行转换,以便将“ 1”(真)值转换为该列的标题名称,将0值转换为NaN。生成的df不需要标题。 预期输出:

NaN NaN C   NaN
A   NaN NaN NaN
NaN B   C   D
A   NaN NaN D

遍历行并通过检查分配这些值可能有效,但是没有更快/更通用的熊猫方式吗?

6 个答案:

答案 0 :(得分:2)

在numpy中

np.where(df == 1, df.columns, np.nan)

array([[nan, nan, 'C', nan],
       ['A', nan, nan, nan],
       [nan, 'B', 'C', 'D'],
       ['A', nan, nan, 'D']], dtype=object)

如何将np.array转换为pd.DataFrame(由@jezrael添加)

df = pd.DataFrame(np.where(df == 1, df.columns, np.nan), columns=df.columns)
print (df)
     A    B    C    D
0  NaN  NaN    C  NaN
1    A  NaN  NaN  NaN
2  NaN    B    C    D
3    A  NaN  NaN    D

答案 1 :(得分:2)

也许是DataFrame.apply的东西:

df.apply(lambda s: [s.name if v == 1 else np.nan for v in s])

答案 2 :(得分:1)

您可以使用此:

for i in df.columns:
    df[i] = df[i].apply(lambda x: i if x==1 else np.nan)
df.columns = [''] * len(df.columns)

答案 3 :(得分:1)

您可以使用如下所示的np.where或pd.mask

np.where(df.values==1, df.columns, np.nan)

## or
df.mask(df==1,df.columns)

答案 4 :(得分:1)

如果性能很重要,则将numpy.whereDataFrame构造函数一起使用,并且不使用column参数:

df = pd.DataFrame(np.where(df == 1, df.columns, np.nan))
print (df)
     0    1    2    3
0  NaN  NaN    C  NaN
1    A  NaN  NaN  NaN
2  NaN    B    C    D
3    A  NaN  NaN    D

如果需要在无列和索引值的文件中输出,请在DataFrame.to_csv上添加index=Falseheader=None

df.to_csv('file.csv', index=False, header=None)

编辑:

如果性能很重要,则可以避免使用apply,因为它会在引擎盖下循环。对于矢量化最快,最快的解决方案,最好使用np.where

#[40000 rows x 40 columns]
df = pd.concat([df] * 10000, ignore_index=True)
df = pd.concat([df] * 10, ignore_index=True, axis=1)


In [180]: %%timeit
     ...: for i in df.columns:
     ...:     df[i] = df[i].apply(lambda x: i if x==1 else np.nan)
     ...:     
690 ms ± 13.2 ms per loop (mean ± std. dev. of 7 runs, 1 loop each)

In [181]: %%timeit
     ...: df.apply(lambda s: [s.name if v == 1 else np.nan for v in s])
     ...: 
680 ms ± 23 ms per loop (mean ± std. dev. of 7 runs, 1 loop each)

In [182]: %%timeit
     ...: pd.DataFrame(np.where(df == 1, df.columns, np.nan))
     ...: 
42.7 ms ± 3.26 ms per loop (mean ± std. dev. of 7 runs, 10 loops each)

In [183]: %%timeit
     ...: df.T.where(df.T != 1, df.columns).T.where(df != 0, np.nan)
     ...: 
17 s ± 644 ms per loop (mean ± std. dev. of 7 runs, 1 loop each)

答案 5 :(得分:0)

您还可以使用where中的pandas

https://pandas.pydata.org/pandas-docs/stable/reference/api/pandas.DataFrame.where.html

请注意,T对于获得适当的结果很重要。

import pandas as pd
import numpy as np


df = pd.DataFrame({'A': [0,1,0,1],
                   'B': [0,0,1,0],
                   'C': [1,0,1,0],
                   'D': [0,0,1,1]
                   })


df = df.T.where(df.T != 1, df.columns).T.where(df != 0, np.nan)

输出:

     A    B    C    D
0  NaN  NaN    C  NaN
1    A  NaN  NaN  NaN
2  NaN    B    C    D
3    A  NaN  NaN    D