【问题标题】:Sort rows of a dataframe in descending order of NaN counts按 NaN 计数的降序对数据帧的行进行排序
【发布时间】:2018-02-05 04:17:45
【问题描述】:

我正在尝试对以下 Pandas DataFrame 进行排序:

         RHS  age  height  shoe_size  weight
0     weight  NaN     0.0        0.0     1.0
1  shoe_size  NaN     0.0        1.0     NaN
2  shoe_size  3.0     0.0        0.0     NaN
3     weight  3.0     0.0        0.0     1.0
4        age  3.0     0.0        0.0     1.0

以这样一种方式,将具有更多 NaN 列的行首先定位。 更准确地说,在上面的df中,索引为1(2个Nans)的行应该排在索引为0(1个NaN)的行之前。

我现在要做的是:

df.sort_values(by=['age', 'height', 'shoe_size', 'weight'], na_position="first")

【问题讨论】:

    标签: python pandas sorting dataframe nan


    【解决方案1】:

    df.isnull().sum().sort_values(ascending=False)

    【讨论】:

    • 请始终将您的答案放在上下文中,而不仅仅是粘贴代码。有关详细信息,请参阅here
    【解决方案2】:

    使用基于df.sort_valuesloc 的访问。

    df = df.iloc[df.isnull().sum(1).sort_values(ascending=0).index]
    print(df)
    
             RHS  age  height  shoe_size  weight
    1  shoe_size  NaN     0.0        1.0     NaN
    2  shoe_size  3.0     0.0        0.0     NaN
    0     weight  NaN     0.0        0.0     1.0
    4        age  3.0     0.0        0.0     1.0
    3     weight  3.0     0.0        0.0     1.0
    

    df.isnull().sum(1)NaNs 进行计数,并根据此排序计数访问行。


    @ayhan 为上述解决方案提供了nice little improvement,涉及pd.Series.argsort

    df = df.iloc[df.isnull().sum(axis=1).mul(-1).argsort()]
    print(df)
    
             RHS  age  height  shoe_size  weight 
    1  shoe_size  NaN     0.0        1.0     NaN           
    0     weight  NaN     0.0        0.0     1.0           
    2  shoe_size  3.0     0.0        0.0     NaN           
    3     weight  3.0     0.0        0.0     1.0           
    4        age  3.0     0.0        0.0     1.0            
    

    【讨论】:

    • 排序和获取索引可以使用 argsort 在一个操作中完成。 df.iloc[np.argsort(-df.isnull().sum(axis=1))] 它也在 pd.Series 上定义为一种方法。 df.iloc[df.isnull().sum(axis=1).mul(-1).argsort()] 非常相似,所以我想我会把它留在这里而不是发布答案。
    • @ayhan 哦,太好了!如果您不介意,请将其添加到我的答案中。
    • 当然。这就是我发表评论的原因。 :)
    • @cᴏʟᴅsᴘᴇᴇᴅ 或者df.iloc[df.stack().groupby(level=0).count().sort_values().index] :)
    • @cms72 最后一步是提取排序后的索引,以便将它们传递给 iloc 以重新排序原始 DataFrame 并获得预期结果。
    【解决方案3】:

    您可以添加一个包含空值数量的列,按该列排序,然后删除该列。是否要使用 .reset_index(drop=True) 重置行数取决于您。

    df['null_count'] = df.isnull().sum(axis=1)
    df.sort_values('null_count', ascending=False).drop('null_count', axis=1)
    
    # returns
             RHS  age  height  shoe_size  weight
    1  shoe_size  NaN     0.0        1.0     NaN
    0     weight  NaN     0.0        0.0     1.0
    2  shoe_size  3.0     0.0        0.0     NaN
    3     weight  3.0     0.0        0.0     1.0
    4        age  3.0     0.0        0.0     1.0
    

    【讨论】:

      【解决方案4】:

      这是一个可以做到这一点的单线:

      df.assign(Count_NA = lambda x: x.isnull().sum(axis=1)).sort_values('Count_NA', ascending=False).drop('Count_NA', axis=1)
      #          RHS  age  height  shoe_size  weight
      # 1  shoe_size  NaN     0.0        1.0     NaN
      # 0     weight  NaN     0.0        0.0     1.0
      # 2  shoe_size  3.0     0.0        0.0     NaN
      # 3     weight  3.0     0.0        0.0     1.0
      # 4        age  3.0     0.0        0.0     1.0
      

      这通过分配一个临时列(“Count_NA”)来计算每行中的 NA,对该列进行排序,然后将其删除,所有这些都在同一个表达式中。

      【讨论】:

      • 如果它使用 lambda 并且必须创建和删除临时列,则不是一个行列...
      • 同意,这有点老套。使用iloc 更好:)
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2014-02-16
      • 2011-06-28
      • 2021-12-28
      • 1970-01-01
      • 2020-07-18
      • 1970-01-01
      相关资源
      最近更新 更多