这是从调查中收集的数据,其中有一个单选按钮可从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']})
我想最终得到这样的数据框:
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']})
我只有大约65k行数据,所以性能不是我的首选。我最感兴趣的是学习一种很好的方法 - 希望这很简单。如果idxmax相当容易做到这一点真的很好。
答案 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)