如何使用列 header 作为填充值将 Panda Dataframe 从 5 列转换为 1 列?
How do I transform a Panda Dataframe from 5 columns into 1 column using column header as value to populate?
这是从调查中收集的数据,其中有一个单选按钮 select 从 5 个选项中选出 1 个。存储在该列中的是一个简单的 1 作为标志,表示它是 selected.
我想以 headers 列作为值的单个列结束。有人建议在我的数据帧上使用 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 很容易做到这一点,那就太好了。
您可以直接使用 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
select 最大。跨列逐行赋值。
2. drop
删除不需要的列,然后删除 duplicate
个值。
3. 最后,我们根据需要 rename
列。
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)
在下面的代码中,我创建了一个单独检查 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)
这是从调查中收集的数据,其中有一个单选按钮 select 从 5 个选项中选出 1 个。存储在该列中的是一个简单的 1 作为标志,表示它是 selected.
我想以 headers 列作为值的单个列结束。有人建议在我的数据帧上使用 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 很容易做到这一点,那就太好了。
您可以直接使用 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
select 最大。跨列逐行赋值。
2. drop
删除不需要的列,然后删除 duplicate
个值。
3. 最后,我们根据需要 rename
列。
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)
在下面的代码中,我创建了一个单独检查 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)