2016-07-13 75 views
3

我有一系列不规则数量的数据,我需要使用熊猫来确定跨多个柱子的分割部分的最常见值。我的意思的例子,如果我有什么样的奶酪我的同事曾与他们的午餐,每天的信息:熊猫中多个柱子的最常见值

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 

我正在寻找某种功能,这将使所产生的数据透视表:

Name Cheese Pct 
Evan Gouda  .66 
John Havarti .4 

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

回答

4
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) 

输出:

 Cheese  Pct 
Name     
Evan Gouda 0.666667 
John Havarti 0.400000 
Rick  None 0.000000 
+3

你错过了一个命名函数'big_cheese'的机会 – piRSquared

+0

这可以工作,但是当所有的人都有相同的最常见的奶酪时,它就会中断。相反,它将名称作为列标题而不是索引。有什么办法解决这个问题吗? – user3329648

+0

我通过使用try-except语句来修复它,以获得索引或列名称,但它很笨拙,如果有人有一个更好的解决方案,我想要一个更好的解决方案。 – user3329648

0

最近,我一直在使用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) 

,输出:

Name Cheese   p 
    (chr) (chr)  (dbl) 
1 Evan Gouda 0.6666667 
2 John Havarti 0.4000000 

我有兴趣看到Pandas中的相似事物会是怎样的。这是我想出了:

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,但也许有人更熟悉的熊猫可以如何改善这种权衡。