Pythonic эквивалент R с двойным поворотом и фильтром

Задача, с которой я часто сталкиваюсь, похожа на следующее преобразование:

от:

  home_team_id away_team_id home_team away_team
1            1            2   Arsenal Tottenham
2            2            3 Tottenham   Chelsea

к

  team      value
1 Arsenal       1
2 Tottenham     2
3 Tottenham     2
4 Chelsea       3

В своей голове я называю это «двойным поворотом», хотя, возможно, есть более подходящее название.

В R я могу сделать это (списано с головы - я уверен, что gsub можно несколько оптимизировать/очистить):

library(tidyverse)
example_df_R = data.frame(
  home_team_id = c(1, 2), 
  away_team_id = c(2,3), 
  home_team = c("Arsenal", "Tottenham"), 
  away_team = c("Tottenham", "Chelsea")
)

example_df_R %>% 
  pivot_longer(cols = ends_with("id")) %>% 
  pivot_longer(cols = ends_with("team"), values_to = "team", names_to = "team_location") %>%
  filter(gsub("_id$", "", name) == team_location) %>%
  select(team, value)

В python кажется, что это должно быть эквивалентно:

import pandas as pd

example_df_py = pd.DataFrame(
    {
        "home_team_id": [1, 2],
        "away_team_id": [2, 3],
        "home_team": ["Arsenal", "Tottenham"],
        "away_team": ["Tottenham", "Chelsea"],
    }
)
result = (
    example_df_py.melt(id_vars=["home_team", "away_team"])
    .melt(id_vars=["variable", "value"], var_name = "team_location", value_name = "team")
    .loc[lambda dfr: dfr["variable"].str.startswith(dfr["team_location"].iloc[0])][
        ["team", "value"]
    ]
)

result

однако это дает мне:

        team  value
0    Arsenal      1
1  Tottenham      2
4  Tottenham      1
5    Chelsea      2

Я полностью понимаю, почему я получаю этот результат (я включил iloc, что означает, что он не работает построчно в обоих столбцах, чтобы запустить код), но не уверен, что эквивалентно правильному, «элегантному» (т.е. предпочтительно в цепочке для контекста, который мне часто приходится использовать), код pythonic для R, опубликованного выше

Большое спасибо!

В R короче использовать только один pivot_longer: example_df_R %>% pivot_longer(ends_with("id")) %>% mutate(team = ifelse(name == "home_team_id", home_team, away_team)) %>% select(team, value)

G. Grothendieck 16.01.2023 16:40
Почему в Python есть оператор "pass"?
Почему в Python есть оператор "pass"?
Оператор pass в Python - это простая концепция, которую могут быстро освоить даже новички без опыта программирования.
Некоторые методы, о которых вы не знали, что они существуют в Python
Некоторые методы, о которых вы не знали, что они существуют в Python
Python - самый известный и самый простой в изучении язык в наши дни. Имея широкий спектр применения в области машинного обучения, Data Science,...
Основы Python Часть I
Основы Python Часть I
Вы когда-нибудь задумывались, почему в программах на Python вы видите приведенный ниже код?
LeetCode - 1579. Удаление максимального числа ребер для сохранения полной проходимости графа
LeetCode - 1579. Удаление максимального числа ребер для сохранения полной проходимости графа
Алиса и Боб имеют неориентированный граф из n узлов и трех типов ребер:
Оптимизация кода с помощью тернарного оператора Python
Оптимизация кода с помощью тернарного оператора Python
И последнее, что мы хотели бы показать вам, прежде чем двигаться дальше, это
Советы по эффективной веб-разработке с помощью Python
Советы по эффективной веб-разработке с помощью Python
Как веб-разработчик, Python может стать мощным инструментом для создания эффективных и масштабируемых веб-приложений.
1
1
55
1
Перейти к ответу Данный вопрос помечен как решенный

Ответы 1

Ответ принят как подходящий

Я не знаю, лучший ли это способ сделать это (или самый элегантный XD), но мне удалось добиться ожидаемых результатов с помощью кортежей и метода взорвать.

    (example_df_py
     .assign(team=lambda df: df[["home_team", "away_team"]].apply(tuple, axis=1), # (team1, team2), ...
             value=lambda df: df[["home_team_id", "away_team_id"]].apply(tuple, axis=1)) # (id1, id2), ...
     .explode(["team", "value"])
     .loc[:, ["team", "value"]]
     .reset_index(drop=True)
    )
    team      value
0   Arsenal       1
1   Tottenham     2
2   Tottenham     2
3   Chelsea       3

о, это действительно приятно - не встречал explode раньше

Robert Hickman 16.01.2023 16:45

Другие вопросы по теме