每个产品/嵌套字典组合保存到 DataFram 中

2024-04-16 14:49:19 发布

您现在位置:Python中文网/ 问答频道 /正文

我对Python还不熟悉,并为X个模型运行初始化参数。我需要从N个字典中创建每个可能的组合,每个字典都有嵌套的数据。你知道吗

我知道我需要itertools.产品不知怎么的,但我被困在如何浏览字典。也许我不应该使用字典,而是json之类的。我还知道这将创建许多参数/运行。你知道吗

编辑:添加了评论中的澄清。 我想创建一个函数,将n个字典(例如def func(dict*))作为输入,并在所有字典中创建所有这些单独键/值对的所有可能组合,返回一个包含所有组合的大DF。你知道吗

我的数据如下:

词典1
{
    "chisel": [
        {"type": "chisel"},
        {"depth": [152, 178, 203]},
        {"residue incorporation": [0.4, 0.5, 0.6, 0.7, 0.8, 0.9, 1.0]},
        {"timing": ["10-nov", "10-apr"]},
    ],
    "disc": [
        {"type": "disc"},
        {"depth": [127, 152, 178, 203]},
        {"residue incorporation": [0.4, 0.5, 0.6, 0.7, 0.8, 0.9, 1.0]},
        {"timing": ["10-nov", "10-apr"]},
    ],
    "no_till": [
        {"type": "user_defined"},
        {"depth": [0]},
        {"residue incorporation": [0.0]},
        {"timing": ["10-apr"]},
    ],
}
词典2
{
    "nh4_n":
        {
            "kg/ha":[110, 115, 120, 125, 130, 135, 140, 145, 150, 155, 160, 165, 170, 175, 180, 185, 190, 195, 200, 205, 210, 215, 220, 225],
            "fertilize_on":"10-apr"
        },
    "urea_n":
        {
            "kg/ha":[110, 115, 120, 125, 130, 135, 140, 145, 150, 155, 160, 165, 170, 175, 180, 185, 190, 195, 200, 205, 210, 215, 220, 225],
            "fertilize_on":"10-apr"
        }
}
词典3
{
    "maize": {
        "sow_crop": 'maize',
        "cultivar": ['B_105', 'B_110'],
        "planting_dates": [
            '20-apr', '27-apr', '4-may', '11-may', '18-may', '25-may', '1-jun', '8-jun', '15-jun'],
        "sowing_density": [8],
        "sowing_depth": [51],
        "harvest": ['maize'],
    }
}

例如,有了上面的三本词典,我就用dict“凿”和itertools.产品它以某种方式与dict 2中的每一个嵌套字典(例如“nh4\n”)和dict 3中的每一个嵌套字典(在这种情况下,只有一个,因此与每个不同的品种、种植日期等)。我还想使用每个键值对中的键作为DF列标题。你知道吗

enter image description here


Tags: 数据参数字典typedictaprjunmay
1条回答
网友
1楼 · 发布于 2024-04-16 14:49:19

问题:

  • 主要问题是数据dict格式不一致:

    1. 与dict 1&3不同,dict 2的顶键不是子键的值
    2. 与dict2&3不同,dict1将dicts作为主键的值 具有顶级值的dict列表。你知道吗
    3. 有些第二级值是字符串,有些是列表

步骤1:修复数据:

功能:

fix_list_dicts

def fix_list_dicts(data: dict) -> dict:
    """
    Given a dict where the values are a list of dicts:
    (1) convert the value to a dict of dicts
    (2) if any second level value is a str, convert it to a list
    """
    data_new = dict()
    for k, v in data.items():
        v_new = dict()
        for x in v:
            for k1, v1 in x.items():
                if type(v1) != list:
                    x[k1] = [v1]
            v_new.update(x)
        data_new[k] = v_new
    return data_new

add_top_key_as_value

def add_top_key_as_value(data: dict, new_key: str) -> dict:
    """
    Given a dict of dicts, where top key is not a 2nd level value:
    (1) add new key: value pair to second level
    """
    for k, v in data.items():
        v.update({new_key: k})
        data[k] = v
    return data

str_value_to_list

def str_value_to_list(data: dict) -> dict:
    """
    Given a dict of dicts:
    (1) Convert any second level value from str to list
    """    
    for k, v in data.items():
        for k2, v2 in v.items():
            if type(v2) != list:
                data[k][k2] = [v2]
    return data 

实施:

from pprint import pprint as pp

词典1:

d1 = fix_list_dicts(d1)
pp(d1)

{'chisel': {'depth': [152, 178, 203],
            'residue incorporation': [0.4, 0.5, 0.6, 0.7, 0.8, 0.9, 1.0],
            'timing': ['10-nov', '10-apr'],
            'type': ['chisel']},
 'disc': {'depth': [127, 152, 178, 203],
          'residue incorporation': [0.4, 0.5, 0.6, 0.7, 0.8, 0.9, 1.0],
          'timing': ['10-nov', '10-apr'],
          'type': ['disc']},
 'no_till': {'depth': [0],
             'residue incorporation': [0.0],
             'timing': ['10-apr'],
             'type': ['user_defined']}}

词典2:

d2 = add_top_key_as_value(d2, 'fertilizer')
d2 = str_value_to_list(d2)

{'nh4_n': {'fertilize_on': ['10-apr'],
           'fertilizer': ['nh4_n'],
           'kg/ha': [110, 115, 120, 125, 130, 135, 140, 145, 150, 155, 160, 165, 170, 175, 180, 185, 190, 195, 200, 205, 210, 215, 220, 225]},
 'urea_n': {'fertilize_on': ['10-apr'],
            'fertilizer': ['urea_n'],
            'kg/ha': [110, 115, 120, 125, 130, 135, 140, 145, 150, 155, 160, 165, 170, 175, 180, 185, 190, 195, 200, 205, 210, 215, 220, 225]}}

词典3:

d3 = str_value_to_list(d3)

{'maize': {'cultivar': ['B_105', 'B_110'],
           'harvest': ['maize'],
           'planting_dates': ['20-apr', '27-apr', '4-may', '11-may', '18-may', '25-may', '1-jun', '8-jun', '15-jun'],
           'sow_crop': ['maize'],
           'sowing_density': [8],
           'sowing_depth': [51]}}

步骤2:将数据合并到数据帧中:

功能:

import pandas as pd

combine_the_data

def combine_the_data(data: list) -> dict:
    """
    Given a list of dicts:
    (1) convert each dict into DataFrame
    (2) set the indices to 0
    (3) add each DataFrame to df_dict
    """
    df_dict = dict()
    for i, d in enumerate(data):
        df = pd.DataFrame.from_dict(d, orient='index')
        df.index = [0 for _ in range(len(df))]
        df_dict[f'd_{i}'] = df

    return df_dict

merge_df_dict

def merge_df_dict(data: dict) -> pd.DataFrame:
    """
    Given a dict of DataFrames
    (1) merge them on the index
    """
    df = pd.DataFrame()
    for _, v in data.items():
        df = df.merge(v, how='outer', left_index=True, right_index=True)
    return df

实施:

data = [d1, d2, d3]
df_dict = combine_the_data(data)

df_dict['d_0']

enter image description here

df_dict['d_1']

enter image description here

df_dict['d_2']

enter image description here

df = merge_df_dict(df_dict)

enter image description here


第三步:使用pd.DataFrame.explode分解所有列表:

  • 我不知道pandasv0.25还有哪些新特性,但是explode是其中最好的。你知道吗
  • 没有pandasv0.25?那就去拿!你知道吗
df.reset_index(drop=True, inplace=True)  # the DataFrame must have a unique 0...x index

for col in df.columns:
    df = df.explode(col).reset_index(drop=True)

所有组合的最终输出:

enter image description here

价值统计和期望:

给定:

enter image description here

  • len(kg/ha) = 24
  • len(cultivar) = 2
  • len(plantint_dates) = 9
  • user_defined行数=2

  • user_defined=864的总组合

  • 我没有手动计算另外两个types,但是由于user_defined有正确的组合数,我希望其他的也有。

df.type.value_counts()

disc            48384
chisel          36288
user_defined      864
Name: type, dtype: int64

相关问题 更多 >