将嵌套列表的字典转换为数据框中的行

问题描述 投票:0回答:1

我有一些数据(如下所示),它是字典嵌套列表的字典。 我想把整个字典排成一行。很宽的一排。 目前我已经可以得到我想要的结果了。它很长而且不太优雅。 我想更好地编写更简洁的代码,并希望代码计算效率更高。

就上下文而言,我正在为一个大学项目做这个。我们并没有在代码优雅或优化方面得到标记。这更多是为了我自己的利益。

对 python 来说还是个新手,我不太擅长使用字典的嵌套字典和嵌套字典列表。 任何帮助将不胜感激!

数据字典

{'attack': [{'stat': 'carries_crossed_gain_line', 'value': '52'},
  {'stat': 'carries_metres', 'value': '648'},
  {'stat': 'carries_not_made_gain_line', 'value': '64'},
  {'stat': 'clean_breaks', 'value': '21'},
  {'stat': 'defenders_beaten', 'value': '25'},
  {'stat': 'offload', 'value': '16'},
  {'stat': 'passes', 'value': '168'},
  {'stat': 'runs', 'value': '138'},
  {'stat': 'turnovers_conceded', 'value': '16'}],
 'defence': [{'stat': 'missed_tackles', 'value': '32'},
  {'stat': 'tackles', 'value': '125'},
  {'stat': 'turnovers_won', 'value': '6'}],
 'discipline': [{'stat': 'penalties_conceded', 'value': '12'},
  {'stat': 'red_card_second_yellow', 'value': '0'},
  {'stat': 'red_cards', 'value': '0'},
  {'stat': 'yellow_cards', 'value': '0'}],
 'kicking': [{'stat': 'conversion_goals', 'value': '3'},
  {'stat': 'kicks_from_hand', 'value': '10'},
  {'stat': 'missed_conversion_goals', 'value': '1'},
  {'stat': 'missed_penalty_goals', 'value': '0'},
  {'stat': 'penalty_goals', 'value': '2'}],
 'breakdown': [{'stat': 'mauls_lost', 'value': '0'},
  {'stat': 'mauls_total', 'value': '6'},
  {'stat': 'mauls_won', 'value': '6'},
  {'stat': 'mauls_won_penalty', 'value': '1'},
  {'stat': 'mauls_won_try', 'value': '0'},
  {'stat': 'rucks_lost', 'value': '11'},
  {'stat': 'rucks_total', 'value': '99'},
  {'stat': 'rucks_won', 'value': '88'}],
 'lineouts': [{'stat': 'lineout_success', 'value': '0.93'},
  {'stat': 'lineout_won_steal', 'value': '1'},
  {'stat': 'lineouts_Lost', 'value': '1'},
  {'stat': 'lineouts_won', 'value': '14'}],
 'scrums': [{'stat': 'scrums_lost', 'value': '0'},
  {'stat': 'scrums_success', 'value': '1.00'},
  {'stat': 'scrums_won', 'value': '2'}],
 'possession': [{'stat': 'possession', 'value': '0.50'},
  {'stat': 'pc_possession_first', 'value': '0.50'},
  {'stat': 'pc_possession_second', 'value': '0.50'},
  {'stat': 'ball_possession_last_10_mins', 'value': '0.61'}]}

期望的结果 宽行,例如: enter image description here

我尝试过的 我创建了一个函数,可以用来调用每个嵌套 DF,如下所示:

def trim(df):
    x = df.transpose()
    x.columns = x.iloc[0]
    x = x[1:]
    
    return x

我这样称呼。将最后一次“攻击”更改为其他统计数据:

trim(pd.DataFrame(results['home']['team_stats']['attack']))

然后我

  1. 将帧连接成一行。
  2. 为所有列添加“home”前缀。
  3. 对客队重复步骤一和步骤二,在列中添加前缀“客场”
  4. 将两个结果连接成一个非常非常宽的行。
  5. 将比赛详细信息元数据添加到该行,使其非常非常宽。
  6. 对每组比赛数据重复此操作。

这很耗时。有没有一种方法可以让我以更有效或Pythonic的方式做到这一点? 我的最终目标是收集主队和客队的比赛数据(因此将数据框宽度加倍)并每场比赛一行。

额外数据供参考 结果:我只对 ['match']、['home'] 和 ['away'] 字典感兴趣。 在主客场词典中,“team_stats”部分是我试图提取的内容。 该数据来自 API。我首先将响应转换为 json 格式。 每场比赛我都会处理一组这样的数据。目标是进行大约 250 场以上的比赛。

数据

python pandas dictionary data-science data-wrangling
1个回答
0
投票

试试这个:

# Assuming `rugby_data`` is the deserialized JSON object from your sample input
df = (
    pd.DataFrame(
        # The idea is to convert rugby_data to a list of 3-tuples:
        #   [
        #       ("match", "id", 3195835),
        #       ("match", "comp_id", 2142),
        #       ...
        #       ("home", "carries_crossed_gain_line", "52"),
        #       ("home", "carries_metres", "648"),
        #       ...
        #       ("away", "carries_crossed_gain_line", "59"),
        #       ("away", "carries_metres", "561"),
        #       ...
        #   ]
        [("match", key, value) for key, value in rugby_data["match"].items()]
        + [
            (side, stat["stat"], stat["value"])
            for side in ["home", "away"]
            for _, stats in rugby_data[side]["team_stats"].items()
            for stat in stats
        ],
        columns=["category", "key", "value"],
    )
    # Then transform it to a wide format
    .set_index(["category", "key"])
    .T
)

# Your stats are all strings. Convert them to floats for numerical operations
# later on
for (category, key) in df.columns:
    if category in ["home", "away"]:
        df[category, key] = df[category, key].astype(float)

# I would recommend using a MultiIndex for the columns:
#   df[("match", "venue")]
#   df[("home", "carries_crossed_gain_line")]
#   df[("away", "conversion_goals")]
# but if you want to, you can flatten the column levels:
df.columns = df.columns.map("_".join)

# Now you can refer to columns like:
#   df["match_venue"]
#   df["home_carries_crossed_gain_line"]
#   df["away_conversion_goals"]
© www.soinside.com 2019 - 2024. All rights reserved.