Как сравнить целочисленные значения в кадре данных панд - PullRequest
0 голосов
/ 02 сентября 2018

Я пишу программу, которая должна прочитать CSV / текстовый файл с результатами футбольных матчей, который выглядит следующим образом:

Lions 3, Snakes 3 
Tarantulas 1, FC Awesome 0 
Lions 1, FC Awesome 1 
Tarantulas 3, Snakes 1 
Lions 4, Grouches 0

Если команды играют вничью, каждая команда получает 1 очко, если команда побеждает, она получает 3 очка.

В идеале вывод должен выглядеть следующим образом:

1. Tarantulas, 6 pts 
2. Lions, 5 pts 
3. FC Awesome, 1 pt 
3. Snakes, 1 pt 
4. Grouches, 0 pts 

Это код, который у меня есть:

import pandas as pd


data = pd.read_csv("sample_input.csv", header=None, names=['left_team', 'right_team'])
data_dict = data.to_dict(orient='list')


def splitter(row):
    left_team, right_team = row.split(',')
    return {
       'left_team': left_team[:-2].strip(),
       'left_score': int(left_team[-2:].strip()),
       'right_team': right_team[:-2].strip(),
       'right_score': int(right_team[-2:].strip())
}

Мой вопрос: как мне получить данные из фрейма данных для сравнения значений? Я также пытался кодировать решение без панд, но я борюсь с этим. Любая помощь будет оценена! Спасибо!

Это другое решение, которое я пробовал:

from collections import defaultdict
import csv


reader = csv.DictReader(open('sample_input.csv', 'r'))

dict_list = []

for line in reader:
    dict_list.append(line)


data_list = [splitter(row) for row in reader]


def splitter(row):
    left_team, right_team = row.split(',')
    return {
       'left_team': left_team[:-2].strip(),
       'left_score': int(left_team[-2:].strip()),
       'right_team': right_team[:-2].strip(),
       'right_score': int(right_team[-2:].strip())
}


data_dicts = [splitter(row) for row in reader]


team_scores = defaultdict(int)

for game in data_dicts:
    if game['left_score'] == game['right_score']:
        team_scores[game['left']] += 1
        team_scores[game['right']] += 1
    elif game ['left_score'] > game['right_score']:
        team_scores[game['left']] += 3
    else:
        team_scores[game['right']] += 3


teams_sorted = sorted(team_scores.items(), key=lambda team: team[1], reverse=True)

for line in teams_sorted:
    print(line)

Ответы [ 2 ]

0 голосов
/ 03 сентября 2018

Никакой магии здесь. Просто определите функцию, которая переводит оценки в баллы, применяет их, разворачивает влево / вправо, группирует по команде и суммирует баллы. Там может быть более элегантное решение.

Подготовьте данные, используя вашу функцию:

data = '''Lions 3, Snakes 3 
Tarantulas 1, FC Awesome 0 
Lions 1, FC Awesome 1 
Tarantulas 3, Snakes 1 
Lions 4, Grouches 0'''

def splitter(row):
    left_team, right_team = row.split(',')
    return {
       'left_team': left_team[:-2].strip(),
       'left_score': int(left_team[-2:].strip()),
       'right_team': right_team[:-2].strip(),
       'right_score': int(right_team[-2:].strip())
}

data = pd.DataFrame(splitter(row) for row in data.split("\n"))
print(data)

Out:
       left_score   left_team  right_score  right_team
0           3       Lions            3      Snakes
1           1  Tarantulas            0  FC Awesome
2           1       Lions            1  FC Awesome
3           3  Tarantulas            1      Snakes
4           4       Lions            0    Grouches

Добавить столбцы очков команд, используя их оценки

def points(left_score, right_score):

    win_points = 3
    draw_points = 1
    lose_points = 0

    if left_score < right_score:
        return pd.Series({'left_points': lose_points, 'right_points': win_points})
    elif left_score > right_score:
        return pd.Series({'left_points': win_points, 'right_points': lose_points})
    else:
        return pd.Series({'left_points': draw_points, 'right_points': draw_points})

data = data.merge(
    data[['left_score', 'right_score']].apply(lambda row: points(*row), axis=1),
    left_index=True, right_index=True
)
print(data)

Out:
   left_score   left_team  right_score  right_team  left_points  right_points
0           3       Lions            3      Snakes            1             1
1           1  Tarantulas            0  FC Awesome            3             0
2           1       Lions            1  FC Awesome            1             1
3           3  Tarantulas            1      Snakes            3             0
4           4       Lions            0    Grouches            3             0

UNPIVOT:

data = pd.concat([
    data[['left_team', 'left_points']]\
    .rename({'left_team': 'team', 'left_points': 'points'}, axis=1),
    data[['right_team', 'right_points']]\
    .rename({'right_team': 'team', 'right_points': 'points'}, axis=1)
])

print(data)

Out:
         team  points
0       Lions       1
1  Tarantulas       3
2       Lions       1
3  Tarantulas       3
4       Lions       3
0      Snakes       1
1  FC Awesome       0
2  FC Awesome       1
3      Snakes       0
4    Grouches       0

Сгруппируйте, чтобы получить окончательный результат:

result = data.groupby("team")["points"].sum()
print(result)

Out:
team
FC Awesome    1
Grouches      0
Lions         5
Snakes        1
Tarantulas    6
Name: points, dtype: int64
0 голосов
/ 03 сентября 2018

Вот простое решение. Первый шаг очищает данные, а затем просто присваивает очки каждой команде. В конце вы складываете все очки для каждой команды, независимо от того, появляются они слева или справа.

import pandas as pd
import numpy as np

# Create DataFrame from your input
df = pd.read_clipboard(sep=', ', header=None)
df.columns=['l_team', 'r_team']

# Clean the data, separating teams and their score. 
df[['l_team', 'l_score']] = df.l_team.str.extract('(.*)\s(\d+)')
df[['r_team', 'r_score']] = df.r_team.str.extract('(.*)\s(\d+)')
df[['l_score', 'r_score']] = df[['l_score', 'r_score']].astype('int')

Теперь df выглядит так:

       l_team      r_team  l_score  r_score
0       Lions      Snakes        3        3
1  Tarantulas  FC Awesome        1        0
2       Lions  FC Awesome        1        1
3  Tarantulas      Snakes        3        1
4       Lions    Grouches        4        0

Определите, сколько очков набрали команды слева или справа и сложите по командам. Мы используем Series.add, поэтому он выравнивается по индексу, который после groupby является просто названием команды.

df['l_pts'] = np.select([df.l_score > df.r_score, df.l_score == df.r_score], [3, 1], 0)
df['r_pts'] = np.select([df.r_score > df.l_score, df.r_score == df.l_score], [3, 1], 0)

scores df.groupby('l_team').l_pts.sum().add(df.groupby('r_team').r_pts.sum(), fill_value=0).astype('int').sort_values(ascending=False)

Выход: scores

Tarantulas    6
Lions         5
Snakes        1
FC Awesome    1
Grouches      0
dtype: int32

Чтобы точно соответствовать вашему выводу, вы можете сделать что-то вроде:

pd.Series(scores.index+', '+scores.values.astype('str')+' pts', index=np.arange(1,len(scores)+1,1))
#1    Tarantulas, 6 pts
#2         Lions, 5 pts
#3        Snakes, 1 pts
#4    FC Awesome, 1 pts
#5      Grouches, 0 pts
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...