2017-04-25 65 views
3

我有一个比赛结果的数据框。我想创建一个系列,将最后一个阶段的位置和所有阶段的平均值相减。下面是DF一小部分(可能有多个阶段,国家和行)基于熊猫单元格值的索引列

race_location  stage1_position stage2_position stage3_position number_of_stages 
AUS    2.0    2.0    NaN    2 
AUS    1.0    5.0    NaN    2 
AUS    3.0    4.0    NaN    2 
AUS    4.0    8.0    NaN    2 
AUS    10.0    6.0    NaN    2 
AUS    9.0    7.0    NaN    2 
FRA    23.0    1.0    10.0    3 
FRA    6.0    12.0    24.0    3 
FRA    14.0    11.0    14.0    3 
FRA    18.0    10.0    1.0    3 
FRA    15.0    14.0    4.0    3 
USA    24.0    NaN    NaN    1 
USA    7.0    NaN    NaN    1 
USA    22.0    NaN    NaN    1 
USA    11.0    NaN    NaN    1 
USA    8.0    NaN    NaN    1 
USA    16.0    NaN    NaN    1 
USA    13.0    NaN    NaN    1 
USA    19.0    NaN    NaN    1 
USA    5.0    NaN    NaN    1 
USA    25.0    NaN    NaN    1 

输出将

last_stage_minus_average 
0 
4 
1 
4 
-4 
-2 
-2 
15 
1.5    
-13    
-10.5   
0 
0 
0 
0 
0 
0 
0 
0 
0 
0 
0 

这不会工作,但我的想法是这样的:

new_series = [] 
for country in country_list: 

    num_stages = df.loc[df['race_location'] == country, 'number_of_stages'] 

    differnce = df.ix[df['race_location'] == country, num_stages] - 
     df.iloc[:, 0:num_stages-1].mean(axis=1) 

    new_series.append(difference) 

我不知道如何去做这件事。任何帮助或方向都会很棒!

回答

2
#use pandas apply to take the mean for the first n-1 stages and subtract from last stage. 
df.apply(lambda x: x.iloc[x.number_of_stages]-np.mean(x.iloc[1:x.number_of_stages]),axis=1).fillna(0) 
Out[264]: 
0  0.0 
1  4.0 
2  1.0 
3  4.0 
4  -4.0 
5  -2.0 
6  -2.0 
7  15.0 
8  1.5 
9 -13.0 
10 -10.5 
11  0.0 
12  0.0 
13  0.0 
14  0.0 
15  0.0 
16  0.0 
17  0.0 
18  0.0 
19  0.0 
20  0.0 
dtype: float64 
+0

谢谢!如何设置数据帧我不得不使用 int(x.number_of_stages) 而不是只有 x.number_of_stages – moto

2

我会用filter得到的只是他stage列,然后stackgroupby

stages = df.filter(regex='^stage\d+.*') 

stages.stack().groupby(level=0).apply(
    lambda x: x.iloc[-1] - x.iloc[:-1].mean() 
).fillna(0) 

0  0.0 
1  4.0 
2  1.0 
3  4.0 
4  -4.0 
5  -2.0 
6  -2.0 
7  15.0 
8  1.5 
9 -13.0 
10 -10.5 
11  0.0 
12  0.0 
13  0.0 
14  0.0 
15  0.0 
16  0.0 
17  0.0 
18  0.0 
19  0.0 
20  0.0 
dtype: float64 

它是如何工作

  • stack会自动下降的NaN值当转换到一系列。
  • 现在位置-1是每个组中的最后一个值,如果我们通过新的多指标
  • 所以第一级分组,我们使用lambda并计算平均值,其每一件事情到最后的价值x.iloc[:-1].mean()
  • 并减去从最后一个值x.iloc[-1]
+0

我与其他答案去因为有时候有些车手没有完成所有的阶段,这意味着即使比赛有3个阶段,骑手可能只有两个记录给他一个不应该有的分值。感谢您的回答!教我新东西! – moto

+0

@EliotJackson是的!这个答案解释了这一点。这就是为什么我得到了同样的结果。这就是为什么我在我的帖子中解释的原因。当我堆叠时,它会丢弃没有记录的阶段。如果您误解了这一点,请重新考虑您的选择。 – piRSquared

0

减去由平均所有阶段是

01前

这不是什么大事,但我只是好奇而已!不同于你想要的输出,但是根据你的描述,如果其中一个参赛者只完成一次比赛,他们的结果不应该是inf或nan而不是0吗? (从谁已经做了2〜3的比赛,但最后一场比赛结果的一个指定它们是平均种族完全相同?像赛车#1对赛车#11〜20)

df_sp = df.filter(regex='^stage\d+.*') 
df['last'] = df_sp.T.fillna(method='ffill').T.iloc[:, -1] 
df['mean'] = (df_sp.sum(axis=1) - df['last'])/(df['number_of_stages'] - 1) 
print(df['last'] - df['mean']) 

0  0.0 
1  4.0 
2  1.0 
3  4.0 
4  -4.0 
5  -2.0 
6  -2.0 
7  15.0 
8  1.5 
9 -13.0 
10 -10.5 
11  NaN 
12  NaN 
13  NaN 
14  NaN 
15  NaN 
16  NaN 
17  NaN 
18  NaN 
19  NaN 
20  NaN 
+0

这是一个很棒的点!数据框的设置方式,每种不同的race_location完全不同,不是所有的参赛者都参加每场比赛。 我想问题是如果那场比赛只有一个阶段,我们应该给一个骑手一样的一致性得分(0与他的平均完成相同)与一个阶段的比赛与8 +阶段的比赛。 – moto