如何使用列标题作为值填充Panda Dataframe从5列转换为1列?

时间:2018-03-21 10:37:56

标签: python pandas dataframe transformation

这是从调查中收集的数据,其中有一个单选按钮可从5个选项中的1个中进行选择。列中存储的内容是一个简单的1作为标记,表示它已被选中。

我希望最终得到一个列,其中列标题为值。有人建议在我的数据框架上使用IDXMAX方法,但是当我查看文档时,我无法弄清楚如何应用它。尽管看起来确实对它很有用......

我有一个数据框:

 old = pd.DataFrame({'a FINSEC_SA' : [1,'NaN','NaN','NaN','NaN',1,'NaN'],
 'b FINSEC_A' : ['NaN',1,'NaN','NaN','NaN','NaN','NaN'],
 'c FINSEC_NO' : ['NaN','NaN',1,'NaN','NaN','NaN','NaN'],
 'd FINSEC_D' : ['NaN','NaN','NaN',1,'NaN','NaN',1],
 'e FINSEC_SD' : ['NaN','NaN','NaN','NaN',1,'NaN','NaN']})

enter image description here

我想最终得到这样的数据框:

new = pd.DataFrame({'Financial Security':['a FINSEC_SA','b FINSEC_A',
'c FINSEC_NO','d FINSEC_D','e FINSEC_SD','a FINSEC_SA','d FINSEC_D']})

enter image description here

我只有大约65k行数据,所以性能不是我的首选。我最感兴趣的是学习一种很好的方法 - 希望这很简单。如果idxmax相当容易做到这一点真的很好。

3 个答案:

答案 0 :(得分:3)

idxmax只适用于数字。首先,我们需要转换NaN' (字符串)到np.NaN(数值)。然后我们可以将每列转换为数字系列:

old = old.replace('NaN', np.NaN)
old = old.apply(pd.to_numeric)

或者你可以用以下内容在一行中完成:

old = old.apply(pd.to_numeric, errors='coerce')

最后,我们可以运行idxmax。您所要做的就是指定轴。 axis = 1得到每行中1(最高值)的位置,axis = 0得到每列中1的位置

new = old.idxmax(axis=1)

您可以在一行中运行代码(如果您在此之后不需要旧版本的副本):

new = old.apply(pd.to_numeric, errors='coerce').idxmax(axis=1)

答案 1 :(得分:1)

您可以直接使用idxmax后跟reset_index来实现此目的。

df = old.idxmax(axis=1).reset_index().drop('index', axis=1).rename(columns={0:'Financial'})

print(df)

      Financial
0   a FINSEC_SA
1   b FINSEC_A
2   c FINSEC_NO
3   d FINSEC_D
4   e FINSEC_SD
5   a FINSEC_SA
6   d FINSEC_D

说明:
1. idxmax选择最大值跨列的值排列。
2. drop删除不需要的列,然后删除duplicate值 3.最后,根据需要我们rename列。

答案 2 :(得分:1)

在下面的代码中,我创建了一个单独检查NaN的函数,因为我认为在实际数据中你将有np.NaN而不是'NaN'(字符串)。您可以相应地修改字符串

def isNaN(num):
    return num == 'NaN'

def getval(x):
    if not isNaN(x['a FINSEC_SA']) : return 'a FINSEC_SA'
    if not isNaN(x['b FINSEC_A']) : return 'b FINSEC_A'
    if not isNaN(x['c FINSEC_NO']) : return 'c FINSEC_NO'
    if not isNaN(x['d FINSEC_D']) : return 'd FINSEC_D'
    if not isNaN(x['e FINSEC_SD']) : return 'e FINSEC_SD'


old.apply(getval, axis=1)

这是可读但不高效的答案。可以使用熔解功能以更有效的方式获得相同的答案 -

old['id'] = old.index
new = pd.melt(old, id_vars= 'id', var_name = 'Financial')
new = new[new['value'] != 'NaN'].drop('value', axis=1).sort_index(axis=0)