#python #pandas
Вопрос:
У меня есть фрейм данных (называемый «игры»), который содержит список баскетбольных игр по ходу игры, в котором я записываю серии очков в отдельных играх (идентификатор игры определяет конкретную игру). Фрейм данных сортируется по совпадениям (т. е. по идентификатору игры).
Пример набора данных «игры»:
GameID TeamID Scoring Streak 0 nbaG1 A 23 1 nbaG1 B 12 2 nbaG1 B 11 3 nbaG1 A 24 4 nbaG1 B 21 5 nbaG2 C 15 6 nbaG2 C 12 7 nbaG2 D 17 8 nbaG2 C 11 9 nbaG2 D 21 10 nbaG3 E 10 11 nbaG3 F 12 12 nbaG3 F 14
Из этого фрейма данных я хотел бы просто создать столбец, в котором отображается название команды соперника в соответствующем матче. Например, в игре 1 (nbaG1) это команда А против Б. Итак, если команда А забьет, в новой колонке «противники» должно быть написано «В». Однако я понятия не имею, как сканировать имена в каждой игре и возвращать значение команды противника…и я не нашел советов в других потоках.
Желаемый результат для моего набора данных «игры»:
GameID TeamID Scoring Streak Opponents 0 nbaG1 A 23 B 1 nbaG1 B 12 A 2 nbaG1 B 11 A 3 nbaG1 A 24 B 4 nbaG1 B 21 A 5 nbaG2 C 15 D 6 nbaG2 C 12 D 7 nbaG2 D 17 C 8 nbaG2 C 11 D 9 nbaG2 D 21 C 10 nbaG3 E 10 F 11 nbaG3 F 12 E 12 nbaG3 F 14 E
Комментарии:
1. Можете ли вы прислать нам часть своего кода, чтобы мы могли воспроизвести его?
2. @VictorSaraivaRocha скопируйте фрейм данных операции и сделайте
df = pd.read_clipboard(sep=r"ss ")
3. Спасибо, Пранав Хосангади! Я этого не знал.
Ответ №1:
Во-первых, сгруппируйте свой фрейм данных по идентификатору игры и вызовите .unique()
, чтобы получить две команды, которые играют в игру
teams = df.groupby("GameID")["TeamID"].unique() # game_teams : GameID nbaG1 [A, B] nbaG2 [C, D] nbaG3 [E, F]
Затем используйте это, чтобы просмотреть обе команды в каждой игре и добавить столбец в исходный кадр данных:
df["Teams"] = teams[df["GameID"]].to_list() # df: GameID TeamID Scoring Streak Teams 0 nbaG1 A 23 [A, B] 1 nbaG1 B 12 [A, B] 2 nbaG1 B 11 [A, B] 3 nbaG1 A 24 [A, B] 4 nbaG1 B 21 [A, B] 5 nbaG2 C 15 [C, D] 6 nbaG2 C 12 [C, D] 7 nbaG2 D 17 [C, D] 8 nbaG2 C 11 [C, D] 9 nbaG2 D 21 [C, D] 10 nbaG3 E 10 [E, F] 11 nbaG3 F 12 [E, F] 12 nbaG3 F 14 [E, F]
Наконец, apply
функция для каждой строки, которая берет элемент из Teams
того, что не находится в TeamID
def select_opponent(row): for team in row["Teams"]: if team != row["TeamID"]: return team return None df["Opponent"] = df.apply(select_opponent, axis=1) # df: GameID TeamID Scoring Streak Teams Opponent 0 nbaG1 A 23 [A, B] B 1 nbaG1 B 12 [A, B] A 2 nbaG1 B 11 [A, B] A 3 nbaG1 A 24 [A, B] B 4 nbaG1 B 21 [A, B] A 5 nbaG2 C 15 [C, D] D 6 nbaG2 C 12 [C, D] D 7 nbaG2 D 17 [C, D] C 8 nbaG2 C 11 [C, D] D 9 nbaG2 D 21 [C, D] C 10 nbaG3 E 10 [E, F] F 11 nbaG3 F 12 [E, F] E 12 nbaG3 F 14 [E, F] E
Комментарии:
1. Хотя ваш ответ в точности соответствует ожиданиям ОП, я не согласен с тем, что у вас нечетное количество строк. Что вы об этом думаете?
2. @Corralien Я не уверен, что понимаю. Почему имеет значение нечетное количество строк, если в каждой
GameID
из них всего две команды? Я думаю, что ваше замешательство связано с тем фактом, что в игре более двух участников (более одного на команду за игру).3. @Corralien Я не уверен, что представляет собой «серия очков» OP, но если вы замените ее, например, «Игроком, набравшим очки», я думаю, это будет иметь больше смысла: в игре может быть нечетное количество игроков, набравших очки, но это не влияет на то, кем были соперники
4. Да, наверное, вы правы! 1 за ваш ответ.
5. Спасибо, Пранав, за этот код, который работал как надо и всегда возвращает команду противника вместе со списком команд за игру 🙂 Просто для уточнения в столбце «Полосы очков» указано количество неотвеченных очков, набранных соответствующей командой. Так, например, в первом ряду команда А набрала 23 очка подряд, без каких-либо очков команды Б. Так что действительно нечетное количество строк вполне вероятно 🙂
Ответ №2:
Для общего подхода, который также работал бы с более чем двумя командами за игру, вы могли бы использовать наборы: сначала вычислите набор команд для каждой игры, затем получите противников для каждой строки, вычисляя разницу в наборе между набором команд и набором, содержащим только саму команду.
teams_per_game = games.groupby('GameID')['TeamID'].apply(set) opponents = [] for i in games.index: opponents.append((teams_per_game.loc[games.loc[i, 'GameID']] - {games.loc[i, 'TeamID']}).pop()) games['Opponents'] = opponents
Комментарии:
1. Спасибо, Арне, это сработало как заклинание и возвращает именно то, что мне нужно, даже для моего большого набора данных!