【问题标题】:How to check how many times value A is bigger than value B如何检查值A比值B大多少倍
【发布时间】:2020-01-19 14:57:54
【问题描述】:

我有一个用 pandas 阅读的 csv: 数据是这样的

home_team    away_team    home_score    away_score
Scotland     England      0             0
England      Scotland     4             2
Scotland     England      2             1
...          ...          ...           ...

我想编写一个带有两个参数的函数 - 两个团队。 它会输出 team1、team2 赢了多少场比赛,以及有多少场平局比赛

我尝试比较分数,但不确定当同一支球队可能同时出现在主客场列时,我将如何编码

def who_won(team1, team2):

    home = data['home_team']
    away = data['away_team']
    home_score = data['home_score']
    away_score = data['away_score']
    counter_won = 0
    counter_lost = 0
    counter_draw = 0
    for item in range(len(data['home_team'])):

        if home_score > away_score:
            home.append(counter_won)
            counter_won = counter_won + 1
        elif home_score < away_score:
            home.append(counter_won)
            counter_lost = counter_lost + 1
        else:
            counter_draw = counter_draw + 1

但我不确定我应该如何继续比较比赛并计算每次赢、输或平的次数。

期望的输出是

England won 1 time versus Scotland
Scotland won 1 time versus England
Scotland and England had one draw

【问题讨论】:

  • 如果您使用的是 Pandas,那么它们是数据框,而不是列表。
  • 您的函数采用名为homeaway 的参数,但如果您并不真正关心哪个球队是主队,哪个队是客队,那么这些参数名称会产生误导。也许将它们命名为team1team2 会更好。
  • 此外,参数值会立即丢失,因为您分配了具有相同名称的局部变量。
  • 是的,有道理,谢谢,会编辑问题。
  • 所以无论home - away如何,您都在计算匹配项?

标签: python pandas list comparison


【解决方案1】:

你可以对你的数据做一些预处理,然后使用 pandas DataFrame 的groupby 方法得到你想要的输出

1) 预处理

添加两列,一列包含一组(主、客)球队,我称之为match,另一列显示比赛result

df['match'] = list(zip(df.home_team, df.away_team))

要获得匹配结果,您需要一个函数:

def match_result(row):
    if row.home_score > row.away_score:
        return row.home_team + ' won'
    elif row.home_score < row.away_score:
        return row.away_team + ' won'
    else:
        return 'draw'
df['result'] = df.apply(match_result, axis=1)

2) 分组方式

然后您过滤数据集以仅包含输入主队和客队之间的比赛。最后,您按结果对数据进行分组并计算每个可能结果的数量:

df.loc[df.match.isin([(team1, team2), (team2, team1)]), 'result'].groupby(df.result).count()

测试

  home_team away_team  home_score  away_score        result  \
0  Scotland   England           0           0          draw   
1   England  Scotland           4           2   England won   
2  Scotland   England           2           1  Scotland won   

                 match  
0  (Scotland, England)  
1  (England, Scotland)  
2  (Scotland, England)
result
England won     1
Scotland won    1
draw            1
Name: result, dtype: int64

【讨论】:

  • 您好,在第二部分中,team1 和 team2 指的是什么?这些名称未在任何地方声明。
  • 假设它在你的函数中,所以它们是两个参数:who_won(team1, team2)
【解决方案2】:

其实away-home的过滤会更容易实现:

df['won'] = np.sign(df['home_score']-df['away_score'])
df.groupby(['home_team','away_team'])['won'].value_counts()

输出:

home_team  away_team  won
England    Scotland   1      1
Scotland   England    0      1
                      1      1
Name: won, dtype: int64

在你的情况下,这有点棘手:

# home team won/lost/tied
df['won'] = np.sign(df['home_score']-df['away_score'])

# we don't care about home/away, so we sort the pair by name
# but we need to revert the result first:
df['won'] = np.where(df['home_team'].lt(df['away_team']),
                     df['won'], -df['won'])

# sort the pair home/away
df[['home_team','away_team']] = np.sort(df[['home_team','away_team']], axis=1)

# value counts:
df.groupby(['home_team','away_team'])['won'].value_counts()

输出:

home_team  away_team  won
England    Scotland   -1     1
                       0     1
                       1     1
Name: won, dtype: int64

【讨论】:

    【解决方案3】:

    我的解决方案考虑了以下细节:

    • 两支球队(team1team2)都可以是 homeaway,但 您想知道 team1 赢/输/与 team2 并列的次数。
    • 源 DataFrame 还包含与其他团队或当 homeaway 球队都是“其他”(不同于我们的 2 感兴趣)。

    要获得结果,请按如下方式定义您的函数:

    def who_won(team1, team2):
        df1 = df.query('home_team == @team1 and away_team == @team2')\
            .set_axis(['tm1', 'tm2', 's1', 's2'], axis=1, inplace=False)
        df2 = df.query('home_team == @team2 and away_team == @team1')\
            .set_axis(['tm2', 'tm1', 's2', 's1'], axis=1, inplace=False)
        df3 = pd.concat([df1, df2], sort=False).reset_index(drop=True)
        dif = df3.s1 - df3.s2
        bins = pd.cut(dif, bins=[-100, -1, 0, 100], labels=['lost', 'draw', 'won'])
        return dif.groupby(bins).count()
    

    注意一个聪明的技巧,当 team2 出现时,我是如何“交换”主客场球队的 home 团队 (df2)。 然后我连接 df1df2,这样 team1 总是在 tm1 柱子。 所以现在 df3.s1 - df3.s2team1 的目标和目标之间的区别 team2 (请注意,其他解决方案未能识别出这种差异)。

    然后,调用 cut 引入了正确的分类名称(lost / draw / 赢了),提供对最终结果的每个组成部分的直观访问。

    为了测试这个功能,我使用了更大的 DataFrame,也包括其他团队:

      home_team away_team  home_score  away_score
    0  Scotland   England           0           0
    1   England  Scotland           4           2
    2   England  Scotland           3           1
    3  Scotland   England           2           1
    4  Scotland     Wales           3           1
    5     Wales  Scotland           2           1
    

    然后我打电话给who_won('England', 'Scotland')得到结果:

    lost    1
    draw    1
    won     2
    dtype: int64
    

    结果是一个 SeriesCategoricalIndex (lost / draw / won)。

    如果您想将此结果重新格式化为所需的输出, 并获得每个“组件”,这很容易。 例如。获得英格兰与苏格兰获胜时的比赛次数, 运行res['won']

    【讨论】:

    • 嗨,我收到以下错误"values have {new} elements".format(old=old_len, new=new_len) ValueError: Length mismatch: Expected axis has 9 elements, new values have 4 elements
    • 我的错 - 我的 csv 有更多行,这很有效,谢谢!
    • 我有一个“日期”列,其中包含2019-09-17 时间格式,我将如何实现过滤输入值与 who_won 函数之间的匹配项的功能?就像调用 `who_won(team1,team2,from_year,to_year)。那么它会输出与现在相同但仅来自所选日期范围的输出?
    • 可能该函数应该有 2 个附加参数(例如 startDateendDate)并且每个 df_query 中的条件应该包括他们。请记住,列类型和这两个参数应该具有相同的类型(可能是 datetime)。
    猜你喜欢
    • 2023-03-15
    • 1970-01-01
    • 1970-01-01
    • 2015-09-03
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多