簡體   English   中英

熊貓按一列的類別在所有表中出現唯一值的頻率

[英]pandas the frequency of occurrence of unique values in all the table by category of one column

有一列有 4 個類別,我想為部分數據的每個唯一值示例顯示其他列值的出現頻率

在此處輸入圖像描述

輸出

在此處輸入圖像描述

從此開始:

df = pd.DataFrame(
    {
        "cat1": ["yes", "no", "yes", "no", "yes"],
        "cat2": ["a", "a", "b", "b", "a"],
        "cat3": ["yes", "no", "no", "yes", "no"],
        "quant": [1, 2, 3, 4, 5],
    }
)

示例數據框:

    cat1 cat2 cat3  quant
0   yes  a    yes   1
1   no   a    no    2
2   yes  b    no    3
3   no   b    yes   4
4   yes  a    no    5

你可以做:

y = lambda x: x.value_counts(normalize=True).loc["yes"]
n = lambda x: x.value_counts(normalize=True).loc["no"]
df.groupby(["cat2"]).agg(
    {
        "cat1": [("yes", y), ("no", n)],
        "cat3": [("yes", y), ("no", n)],
        "quant": ["min", "max", "mean"],
    }
)

結果:

      cat1                  cat3                   quant
      yes           no      yes         no         min  max mean
cat2                            
a     0.666667  0.333333    0.333333    0.666667    1   5   2.666667
b     0.500000  0.500000    0.500000    0.500000    3   4   3.500000

這是一個更強大的版本:

from functools import partial

def agg_func(s: pd.Series, name: str):
    try:
        return s.value_counts(normalize=True).loc[name]
    except KeyError:
        return 0


yes_no_agg = [
    ("yes", partial(agg_func, name="yes")),
    ("no", partial(agg_func, name="no")),
]

df.groupby(["cat2"]).agg(
    {
        "cat1": yes_no_agg,
        "cat3": yes_no_agg,
        "quant": ["min", "max", "mean"],
    }
)

如何按類別生成描述性信息

我建議將兩種情況分開。 一種是數值數據,按類別查看它們的最小值、最大值和平均值。 另一個是標記數據及其頻率分布。

數值數據的最小值、最大值、平均值(按類別)

首先,讓我們准備數據,將'mode'作為類別列和兩個數字字段'Measure1', 'Measure2'

import pandas as pd

data = {'mode': ['i','i','i','ii','ii','iii','ii','iii','ii'],
        'Ofloxacin': ['no','no','no','yes','no','no','yes','no','no'],
        'ChangeMode': ['yes','no','no','yes','no','yes','yes','no','yes'],
        'Measure1': [*range(1, 10)],
        'Measure2': [*range(-9, 0)]}
df = pd.DataFrame(data)

在這種情況下,我建議使用DataFrame.describe來生成數值數據的統計信息:

df.groupby('mode').agg('describe')

在輸出中,我們可以找到min, max, mean
min max 數值數據類別的平均值

標記數據及其按類別的頻率分布

1.不同列的相同標簽

在這種特殊情況下,我們可以看到'Ofloxacin','ChangeMode'列的標簽相同。 出於這個原因,讓我們使用DataFrame(...).stack按類別和字段形成帶有標簽分布數據的行:

columns = ['Ofloxacin','ChangeMode']
df.groupby('mode')[columns].apply(lambda group: (
    pd.DataFrame((group.value_counts(col, True) for col in columns), index=columns)
    .stack(dropna=False)
    .fillna(0)
    .sort_index()
    ) 
)

這是與前一種情況相同數據的輸出:
按類別分配標簽

2.不同列的不同標注。

讓我們添加內容稍微多樣化的新列:

data = {'mode': ['i','i','i','ii','ii','iii','ii','iii','ii'],
        'Ofloxacin': ['no','no','no','yes','no','no','yes','no','no'],
        'ChangeMode': ['yes','no','no','yes','no','yes','yes','no','yes'],
        'Reaction': ['good','bad','so-so','good','good','so-so','bad','bad','good'],
        'DummyData': 'hello my world and all the people out there'.split()}
df = pd.DataFrame(data)

在這種情況下,以前的解決方案將不起作用。 為了解決這個問題,讓我們為預期的列准備一個多索引:

from functools import reduce

columns = ['Ofloxacin','ChangeMode','Reaction','DummyData']
multicol = pd.MultiIndex.from_tuples(
    reduce(
        lambda x, y: x.append(y),
        (
            pd.Index(sorted(df[col].unique()))
            .map(lambda label: (col, label))
            for col in columns
        ),
        pd.Index([])
    )
)

我將使用它將數據存儲在正確的位置,如下所示:

final_output = df.groupby('mode')[columns].apply(
    lambda group:
        pd.DataFrame(
            (group.value_counts(col, True) for col in columns), 
            index=columns 
        ).stack().reindex(multicol)
).fillna(0)

這是最終輸出:

在此處輸入圖像描述


ps Colab 上用於實驗的筆記本

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM