查找数据框中所有分类列中每个值的频率

Finding frequency of each value in all categorical columns across a dataframe

我有一个如下所示的数据框

df = pd.DataFrame(
    {'sub_code' : ['CSE01', 'CSE01', 'CSE01', 
                   'CSE02', 'CSE03', 'CSE04',
                   'CSE05', 'CSE06'],
     'stud_level' : [101, 101, 101, 101, 
                  101, 101, 101, 101],
     'grade' : ['STA','STA','PSA','STA','STA','SSA','PSA','QSA']})

我想做以下事情

a) 获取数据框所有分类列中每个唯一值的频率

我尝试了下面的方法,但它既不高效也不优雅

df['sub_code'].value_counts() # need to key in column name manually
df['grade'].value_counts() # need to key in column name manually
df.select_dtypes(include='object').value_counts() #produces incorrect output

由于我的真实数据有200多列和100k行,有没有有效的方法来做到这一点?

我希望我的输出如下所示。如果有任何其他更好的方式来显示以下输出,我也欢迎。我不知道如何以简洁的方式捕获这些信息。所以,请分享您的建议

使用meltvalue_counts:

out = (df.select_dtypes(object)
       .melt(var_name="Column", value_name="Value")
       .value_counts(dropna=False)
       .reset_index(name="Frequency")
       .sort_values(by=['Column','Frequency','Variable'], ascending=[True,False,True])
       .reset_index(drop=True))

输出:

     Column Variable  Frequency
0     grade      STA          4
1     grade      PSA          2
2     grade      QSA          1
3     grade      SSA          1
4  sub_code    CSE01          3
5  sub_code    CSE02          1
6  sub_code    CSE03          1
7  sub_code    CSE04          1
8  sub_code    CSE05          1
9  sub_code    CSE06          1

另一种方法是使用,get_dummies

  s=pd.get_dummies(df.drop(columns=['stud_level'])).sum(0).to_frame('Freq').reset_index()
s=s['index'].str.split('\_(?=[A-Z0-9]+$)', expand=True).join(s.iloc[:,-1]).rename(columns={0:'Column',1:'Value'})

结果

    Column  Value  Freq
0  sub_code  CSE01     3
1  sub_code  CSE02     1
2  sub_code  CSE03     1
3  sub_code  CSE04     1
4  sub_code  CSE05     1
5  sub_code  CSE06     1
6     grade    PSA     2
7     grade    QSA     1
8     grade    SSA     1
9     grade    STA     4