大Pandas多个柱的最常见值

2024-05-15 12:56:50 发布

您现在位置:Python中文网/ 问答频道 /正文

我有一系列不规则列数的数据,我需要使用pandas从多个列的拆分部分中确定最常见的值。我的意思是,如果我知道同事们每天午餐时吃的是什么奶酪:

Idx Name   Cheese1   Cheese2   Cheese3
0   Evan   Gouda     NaN       NaN
1   John   Cheddar   Havarti   Blue
2   Evan   Cheddar   Gouda     NaN
3   John   Havarti   Swiss     NaN

我正在寻找某种功能,它将生成透视表:

^{pr2}$

我也不知道每次运行脚本时需要包含多少列,只知道它们的格式都是“Cheese”+index。如果John第二天出现了四个cheese,我将需要添加第四列,分析脚本需要能够处理这个问题。在


Tags: 数据name脚本pandasnanjohn午餐同事
2条回答
import io
import pandas as pd

data = io.StringIO("""\
Idx Name   Cheese1   Cheese2   Cheese3
0   Evan   Gouda     NaN       NaN
1   John   Cheddar   Havarti   Blue
2   Evan   Cheddar   Gouda     NaN
3   John   Havarti   Swiss     NaN
4   Rick   NaN       NaN       NaN
""")
df = pd.read_csv(data, delim_whitespace=True)

def top_cheese(g):
    cheese_cols = [col for col in g.columns if col.startswith('Cheese')]
    try:
        out = (g[cheese_cols].stack().value_counts(normalize=True)
                             .reset_index().iloc[0])
        out.index = ['Cheese', 'Pct']
        return out
    except IndexError:
        return pd.Series({'Cheese': 'None', 'Pct': 0})


output = df.groupby('Name').apply(top_cheese)
print(output)

输出:

^{pr2}$

最近,我一直在使用R,在那里我可以解决如下问题:

library(data.table)
library(dplyr)
library(tidyr)

x <- fread('
Idx Name   Cheese1   Cheese2   Cheese3
0   Evan   Gouda     NaN       NaN
1   John   Cheddar   Havarti   Blue
2   Evan   Cheddar   Gouda     NaN
3   John   Havarti   Swiss     NaN', na = 'NaN')

gather(x, , Cheese, matches('Cheese'), na.rm = T) %>%
  group_by(Name, Cheese) %>%
  summarise(n = n()) %>%
  group_by(Name) %>%
  mutate(p = n/sum(n)) %>%
  filter(p == max(p)) %>%
  select(-n)

哪些输出:

^{pr2}$

我很想看看熊猫身上类似的东西会是什么样子。这就是我想到的:

import io
import pandas as pd

x = pd.read_csv(io.StringIO('''
Idx Name   Cheese1   Cheese2   Cheese3
0   Evan   Gouda     NaN       NaN
1   John   Cheddar   Havarti   Blue
2   Evan   Cheddar   Gouda     NaN
3   John   Havarti   Swiss     NaN'''), delim_whitespace=True)

tidy = pd.melt(x, ['Idx', 'Name'], value_name='Cheese').dropna()
tidy = tidy.groupby(['Name', 'Cheese']).size().reset_index(name='n')
tidy['p'] = tidy.groupby('Name')['n'].transform(lambda n: n/sum(n))
tidy[tidy['p'] == tidy.groupby('Name')['p'].transform('max')].drop('n', 1)

哪些输出:

   Name   Cheese         p
1  Evan    Gouda  0.666667
4  John  Havarti  0.400000

绝对没有R那么干净,但是也许更熟悉熊猫的人可以考虑如何改进这一点。在

相关问题 更多 >