numpy Pandas获得列名称的排名,NA

mspsb9vt  于 2023-03-23  发布在  其他
关注(0)|答案(1)|浏览(163)

我有以下 Dataframe :

df1 = pd.DataFrame(data={'val1': [1, np.NaN, 2, 3], 
                         'val2': [np.NaN, 1, np.NaN, np.NaN], 
                         'val3': [3, np.NaN, 1, 1]},
                   index=pd.Series([1, 2, 3, 4], name='index'))
>>> df1
       val1  val2  val3
index
1       1.0   NaN   3.0
2       NaN   1.0   NaN
3       2.0   NaN   1.0
4       3.0   NaN   1.0

引用this answer,我创建了一个以列名作为值的数据框:

i = np.argsort(df1.to_numpy(), axis=1)
r = pd.DataFrame(df1.columns.to_numpy()[i],
                    index=df1.index,
                    columns=range(1, i.shape[1] + 1)).add_prefix('Rank')
>>> r
      Rank1 Rank2 Rank3
index
1      val1  val3  val2
2      val2  val1  val3
3      val3  val1  val2
4      val3  val1  val2

然而,我试图从排名中删除NA值,如下所示:

>>> r
      Rank1 Rank2 Rank3
index
1      val1  val3  NaN
2      val2  NaN   NaN
3      val3  val1  NaN
4      val3  val1  NaN

我相信argsort方法没有任何参数来跳过Null值。我已经尝试将缺失的值转换为(-1),如下所示,但我只能对一个序列而不是一个 Dataframe 这样做:

>>> series = df1.iloc[0]
>>> series.argsort()
val1    0
val2   -1
val3    1
Name: 1, dtype: int64
px9o7tmv

px9o7tmv1#

在这里,我做了一个函数,允许你创建正确处理null情况的排名:

  • 它允许包含NaN值,并避免将这些列用于rank列(将它们的值也保留为NaN)。
  • 它还添加了相应的秩值以轻松Map它们。
  • 有一个额外的参数,以便您按升序或降序排列它们。
  • 添加一个附加列,指定哪些列具有NaN值且未包括在秩列中。这些值将添加到列表中。如果您以后要分析这些情况,此选项非常有用。
# Example DataFrame
import numpy as np
import pandas as pd

dic = {'A': [0, np.nan, 2, np.nan],
      'B': [3, 0, 1, 5],
      'C': [1, 2, 0, np.nan]}
df = pd.DataFrame(dic)
print(df)

     A  B    C
0  0.0  3  1.0
1  NaN  0  2.0
2  2.0  1  0.0
3  NaN  5  NaN
# Function
def fun_rank_columns(df, ascending=False):
    factor = 1 if ascending else -1
    # Rank columns showing ranking of column names
    np_sort = np.argsort(df.to_numpy() * factor, axis=1)
    df_rank = pd.DataFrame(np.array(df.columns)[np_sort], index=df.index, columns=range(1, np_sort.shape[1] + 1))
    
    # Corresponding values for each rank column
    np_sort_value = np.sort(df.to_numpy() * factor, axis=1)
    df_rank_value = pd.DataFrame(np_sort_value, index=df.index, columns=range(1, np_sort_value.shape[1] + 1)) * factor
    
    # Columns with nan values to be replaced
    num_col_rank = df_rank.shape[1]
    df_rank['nan_value'] = df.apply(lambda row: [i for i in df.columns if np.isnan(row[i])], axis=1)
    for col in range(1, num_col_rank + 1):
        condition = df_rank.apply(lambda x: x[col] in x['nan_value'], axis=1)
        df_rank.loc[condition, col] = np.nan
        df_rank_value.loc[condition, col] = np.nan

    # Join Results
    df_rank = df_rank.add_prefix('rank_')
    df_rank_value = df_rank_value.add_prefix('rank_value_')
    df_res = df_rank.join(df_rank_value)
    return df_res
# Apply the function
df_res = fun_rank_columns(df, ascending=True)
print(df_res)

  rank_1 rank_2 rank_3 rank_nan_value  rank_value_1  rank_value_2  rank_value_3
0      A      C      B             []           0.0           1.0           3.0
1      B      C    NaN            [A]           0.0           2.0           NaN
2      C      B      A             []           0.0           1.0           2.0
3      B    NaN    NaN         [A, C]           5.0           NaN           NaN

相关问题