2015-06-02 55 views
2

我把一些數據一起參加2015年女子世界盃足球賽中配對:生成世界盃賽組

import pandas as pd 

df = pd.DataFrame({ 
    'team':['Germany','USA','France','Japan','Sweden','England','Brazil','Canada','Australia','Norway','Netherlands','Spain', 
     'China','New Zealand','South Korea','Switzerland','Mexico','Colombia','Thailand','Nigeria','Ecuador','Ivory Coast','Cameroon','Costa Rica'], 
    'group':['B','D','F','C','D','F','E','A','D','B','A','E','A','A','E','C','F','F','B','D','C','B','C','E'], 
    'fifascore':[2168,2158,2103,2066,2008,2001,1984,1969,1968,1933,1919,1867,1847,1832,1830,1813,1748,1692,1651,1633,1485,1373,1455,1589], 
    'ftescore':[95.6,95.4,92.4,92.7,91.6,89.6,92.2,90.1,88.7,88.7,86.2,84.7,85.2,82.5,84.3,83.7,81.1,78.0,68.0,85.7,63.3,75.6,79.3,72.8] 
    }) 

df.groupby(['group', 'team']).mean() 

output

現在我想生成包含6個可能的配對一個新的數據幀或者每個groupdf內是否匹配,在這樣的格式:

group team1  team2 
A  Canada  China 
A  Canada  Netherlands 
A  Canada  New Zealand 
A  China  Netherlands 
A  China  New Zealand 
A  Netherlands New Zealand 
B  Germany  Ivory Coast 
B  Germany  Norway 
...  

什麼是簡潔,乾淨的方式做這個?我可以通過每個groupteam做一堆循環,但我覺得應該有一個更清晰的矢量化方法,以pandassplit-apply-combine範例來做到這一點。

編輯:我也歡迎任何R的答案,認爲這是比較有趣的R和熊貓的方式在這裏。添加了r標籤。

下面是R型數據的要求,在註釋:

team <- c('Germany','USA','France','Japan','Sweden','England','Brazil','Canada','Australia','Norway','Netherlands','Spain', 
     'China','New Zealand','South Korea','Switzerland','Mexico','Colombia','Thailand','Nigeria','Ecuador','Ivory Coast','Cameroon','Costa Rica') 
group <- c('B','D','F','C','D','F','E','A','D','B','A','E','A','A','E','C','F','F','B','D','C','B','C','E') 
fifascore <- c(2168,2158,2103,2066,2008,2001,1984,1969,1968,1933,1919,1867,1847,1832,1830,1813,1748,1692,1651,1633,1485,1373,1455,1589) 
ftescore <- c(95.6,95.4,92.4,92.7,91.6,89.6,92.2,90.1,88.7,88.7,86.2,84.7,85.2,82.5,84.3,83.7,81.1,78.0,68.0,85.7,63.3,75.6,79.3,72.8) 

df <- data.frame(team, group, fifascore, ftescore) 
+1

可能是更好的,以由組訪問'pd.DataFrame(({GRP:元組(組合(隊,2)) 用於grp,df.groupby(「group」)[「team」]}))' –

回答

3

下面是兩行的解決方案:

import itertools 

for grpname,grpteams in df.groupby('group')['team']: 
    # No need to use grpteams.tolist() to convert from pandas Series to Python list 
    print list(itertools.combinations(grpteams, 2)) 

[('Canada', 'Netherlands'), ('Canada', 'China'), ('Canada', 'New Zealand'), ('Netherlands', 'China'), ('Netherlands', 'New Zealand'), ('China', 'New Zealand')] 
[('Germany', 'Norway'), ('Germany', 'Thailand'), ('Germany', 'Ivory Coast'), ('Norway', 'Thailand'), ('Norway', 'Ivory Coast'), ('Thailand', 'Ivory Coast')] 
[('Japan', 'Switzerland'), ('Japan', 'Ecuador'), ('Japan', 'Cameroon'), ('Switzerland', 'Ecuador'), ('Switzerland', 'Cameroon'), ('Ecuador', 'Cameroon')] 
[('USA', 'Sweden'), ('USA', 'Australia'), ('USA', 'Nigeria'), ('Sweden', 'Australia'), ('Sweden', 'Nigeria'), ('Australia', 'Nigeria')] 
[('Brazil', 'Spain'), ('Brazil', 'South Korea'), ('Brazil', 'Costa Rica'), ('Spain', 'South Korea'), ('Spain', 'Costa Rica'), ('South Korea', 'Costa Rica')] 
[('France', 'England'), ('France', 'Mexico'), ('France', 'Colombia'), ('England', 'Mexico'), ('England', 'Colombia'), ('Mexico', 'Colombia')] 

說明:

首先我們得到的使用df.groupby('group')的每個組內的團隊小組,通過迭代並訪問其「團隊」se以獲得每組中的4個隊伍的列表:

for grpname,grpteams in df.groupby('group')['team']: 
    teamlist = grpteams.tolist() 
... 
['Canada', 'Netherlands', 'China', 'New Zealand'] 
['Germany', 'Norway', 'Thailand', 'Ivory Coast'] 
['Japan', 'Switzerland', 'Ecuador', 'Cameroon'] 
['USA', 'Sweden', 'Australia', 'Nigeria'] 
['Brazil', 'Spain', 'South Korea', 'Costa Rica'] 
['France', 'England', 'Mexico', 'Colombia'] 

然後我們生成團隊元組的全部玩法全部列表。 David Arenburg的帖子提醒我使用itertools.combinations(..., 2)。但是,我們可以使用一個發電機或嵌套的for循環:

def all_play_all(teams): 
    for team1 in teams: 
    for team2 in teams: 
     if team1 < team2: # [Note] We don't need to generate indices then index into teamlist, just use direct string comparison 
     yield (team1,team2) 

>>> [match for match in all_play_all(grpteams)] 
[('France', 'Mexico'), ('England', 'France'), ('England', 'Mexico'), ('Colombia', 'France'), ('Colombia', 'England'), ('Colombia', 'Mexico')] 

注意,我們走了一條捷徑,首先生成索引的所有可能的元組,然後使用這些索引到團隊列表:

>>> T = len(teamlist) + 1 
>>> [(i,j) for i in range(T) for j in range(T) if i<j] 
[(0, 1), (0, 2), (0, 3), (1, 2), (1, 3), (2, 3)] 

(注意:如果我們使用直接比較團隊名稱的方法,它會產生輕微的副作用(按字母順序)組名(它們最初是通過播種排序,而不是按字母順序排序),所以例如'中國'< '荷蘭',所以他們的配對將顯示爲('荷蘭','中國')而不是('中國',荷蘭'))

+0

你不需要調用tolist,'print(list(combinations(grp,2)))''將會做你需要的一切,該組也是第一個創建數據框所需要的項目。 –

+1

@PadraicCunningham:是的,謝謝。在向Series應用函數時,不知道它忽略了熊貓行索引。 – smci

+0

感謝您向我介紹'itertools'!對於那些想用「DataFrame」來到終點的人,我構建了一個'dict'來包含組('@'在@ smci的'for'循環中,'grp'在@ Padraic在問題評論中的方法],使用'DataFrame.from_dict'和'melt'將其轉換爲我想要的格式,然後使用map來將團隊拉出元組。 – selwyth

3

使用R,這裏的使用是在GitHub devel的版本可能data.table溶液

#### To install development version 
## library(devtools) 
## install_github("Rdatatable/data.table", build_vignettes = FALSE) 

library(data.table) ## v >= 1.9.5 
setDT(df)[, transpose(combn(team, 2L, simplify = FALSE)), keyby = group] 
# group   V1   V2 
# 1:  A  Canada Netherlands 
# 2:  A  Canada  China 
# 3:  A  Canada New Zealand 
# 4:  A Netherlands  China 
# 5:  A Netherlands New Zealand 
# 6:  A  China New Zealand 
# 7:  B  Germany  Norway 
# 8:  B  Germany Thailand 
... 
+0

Python等價物是'itertools.combinations(...,2)' – smci