【问题标题】:Pandas assigning column names as values based on condition with Nan'sPandas 根据 Nan 的条件将列名分配为值
【发布时间】:2021-05-06 11:07:51
【问题描述】:

我想在每一行中选择两个最大值,对它们进行排序并将列名作为值。其他值从数据框中删除。

import pandas as pd
d = {'col1': [1, 2, np.nan], 'col2': [2,3,3], 'col3': [3,6,5], 'col4': [4,9,10], 'col5': [5,1, np.nan], 'col6': [7,np.nan,2], 'col7': [np.nan, 5,6]}
df = pd.DataFrame(data=d)

我现在能够获得每行的两个最大值,但根据列值重塑数据框是另一项任务。下面的代码将其余值保留为 Nan。

lasttwo = df.stack().sort_values(ascending=True).groupby(level=0).tail(2).unstack()

这里有另一个线程的示例Find the column names which have top 3 largest values for each row 示例代码在下面,它几乎可以正常工作,除非它不适用于 Nan 值。

last = pd.DataFrame(df.apply(lambda x:list(df.columns[np.array(x).argsort()[::-1][:2]]), axis=1).to_list(),  columns=['Last', 'Second last'])

如何处理这些nan的?

例子:

--- col1 col2 col3 col4 col5 col6 col7
a 1 2 3 4 5 7 Nan
b 2 3 6 9 1 Nan 5
c Nan 3 5 10 Nan 2 6

预期结果:

--- Last Second last
a col6 col5
b col4 col3
c col4 col7

【问题讨论】:

    标签: python pandas dataframe numpy


    【解决方案1】:

    您可以使用其他替代解决方案:

    lasttwo = df.apply(lambda x: pd.Series(x.nlargest(2).index[:2]), axis=1)
    lasttwo.columns = ['Last',  'Second last']
    print (lasttwo)
       Last Second last
    0  col6        col5
    1  col4        col3
    2  col4        col7
    

    或者:

    lasttwo = (df.stack()
                 .sort_values(ascending=False)
                 .reset_index(level=1)
                 .groupby(level=0)['level_1']
                 .apply(lambda x: pd.Series(list(x)[:2]))
                 .unstack())
    lasttwo.columns = ['Last',  'Second last']
    print (lasttwo)
       Last Second last
    0  col6        col5
    1  col4        col3
    2  col4        col7
    

    如果性能很重要,可以使用屏蔽的 numpy 数组:

    a = df.to_numpy()
    mask = np.isnan(a)
    ma = np.ma.masked_array(a, mask=mask)
    print (ma)
    [[1.0 2.0 3.0 4.0 5.0 7.0 --]
     [2.0 3.0 6.0 9.0 1.0 -- 5.0]
     [-- 3.0 5.0 10.0 -- 2.0 6.0]]
    
    arr = df.columns.to_numpy()[ma.argsort(endwith=False, axis=1)[:, ::-1][:, :2]]
    lasttwo = pd.DataFrame(arr,  columns=['Last', 'Second last'])
    print (lasttwo)
       Last Second last
    0  col6        col5
    1  col4        col3
    2  col4        col7
    

    【讨论】:

    • 我真的很喜欢第一个解决方案。它是如此紧凑。谢谢你。如果我认为这个解决方案如下所示,我的想法是否正确: - x.nlargest(2).index[:2]
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2019-03-23
    • 2020-04-09
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2018-07-10
    相关资源
    最近更新 更多