【问题标题】:Convert Dictionary of Dictionaries with list values to a data frame将具有列表值的字典转换为数据框
【发布时间】:2023-01-13 01:16:35
【问题描述】:

我得到了一个非常大的字典,格式如下,我不确定如何将其转换为可用于执行基本功能的数据框。

{
    'hash': {
        'ids': [List of Unique IDs of records this hash has been seen in],
        'weights': [List of weights],
        'values': [List of values],
        'measure_dates': [List of dates]
    }
}

idsweightsvaluesmeasure_dates中的项数在hash中是相同的。不过,不同的hashes 可以有不同数量的项目。这取决于进行测量的频率。

三个记录示例的真实(ish)数据:

{
    'IRR-99876-UTY': {
        'ids': [9912234, 9912237, 45555889],
        'weights': [0.09, 0.09, 0.113],
        'values': [2.31220, 2.31219, 2.73944],
        'measure_dates': ['2021-10-14', '2021-10-15', '2022-12-17']
    },
    'IRR-10881-CKZ': {
        'ids': [45557231],
        'weights': [0.31],
        'values': [5.221001],
        'measure_dates': ['2022-12-31']
    },
    'IRR-881-CKZ': {
        'ids': [24661, 24662, 29431],
        'weights': [0.05, 0.07, 0.105],
        'values': [3.254, 4.500001, 7.3221],
        'measure_dates': ['2018-05-05', '2018-05-06', '2018-07-01']
    }
}

索引中的值对应于进行的相同测量。例如在IRR-881-CKZ 中,有 3 个测量值。

  • 测量 1 于 2018-05-05 进行,id 24661,weight 0.05,value 3.254
  • 2018-05-06 测量 2,id 24662,weight 0.07,value 4.500001
  • 测量 3 于 2018-07-01 进行,id 29431,权重 0.105 和值 7.3221

没有其他索引组合对此散列有效。

我将尝试获取数据的信息:

  • 最常测量哪些哈希。这可以通过ids 列表中的项目数量最多来确定。在此示例中,第一条和第三条记录包含三个项目,因此将是最靠前的结果。我希望能够使用 nlargest()sort_values().head() 之类的东西来获取它,而不是解析每条记录并计算项目的数量。
  • 哪些散列具有两个值之间的平均值。如果我有一定数量的列,我想我可以做类似df['average'] = df[['value1', 'value2']].mean(axis=1) 的事情,但是对于可变数量的值我不确定如何做到这一点。

如何将这个列表字典的字典转换为可用的数据框?

【问题讨论】:

  • df = pd.DataFrame.from_dict(my_dict).T 创建可用的 df。
  • @SomeDude .T 在这里做什么而 Lasse 下面的回答没有?
  • .T 是转置。

标签: python pandas dataframe


【解决方案1】:

您可以在 pandas 中使用 .from_dict() 将其转换为数据框。

import pandas as pd

# dictionary of dictionaries with list values
data = {
    'IRR-99876-UTY': {
        'ids': [9912234, 9912237, 45555889],
        'weights': [0.09, 0.09, 0.113],
        'values': [2.31220, 2.31219, 2.73944],
        'measure_dates': ['2021-10-14', '2021-10-15', '2022-12-17']
    },
    'IRR-10881-CKZ': {
        'ids': [45557231],
        'weights': [0.31],
        'values': [5.221001],
        'measure_dates': ['2022-12-31']
    },
    'IRR-881-CKZ': {
        'ids': [24661, 24662, 29431],
        'weights': [0.05, 0.07, 0.105],
        'values': [3.254, 4.500001, 7.3221],
        'measure_dates': ['2018-05-05', '2018-05-06', '2018-07-01']
    }
}

# convert to data frame
df = pd.DataFrame.from_dict(data, orient='index')

【讨论】:

  • 使用此方法将每个列表放入一列中。如何使用这些列表找到哪些散列具有介于 X 和 Y 之间的平均值?我可以在列表上运行.mean()吗?
  • 是的,您可以执行以下操作 df['values'].mean() 或者您可以使用 apply df['average'] = df['values'].apply(lambda x: sum(x)/len(x))
【解决方案2】:

你需要将这个字典的每个条目转换成它自己的 DataFrame 并将它们连接起来以有效地处理这些数据:

创建可用的 DataFrame

import pandas as pd

data = {
    'IRR-99876-UTY': {
        'ids': [9912234, 9912237, 45555889],
        'weights': [0.09, 0.09, 0.113],
        'values': [2.31220, 2.31219, 2.73944],
        'measure_dates': ['2021-10-14', '2021-10-15', '2022-12-17']
    },
    'IRR-10881-CKZ': {
        'ids': [45557231],
        'weights': [0.31],
        'values': [5.221001],
        'measure_dates': ['2022-12-31']
    },
    'IRR-881-CKZ': {
        'ids': [24661, 24662, 29431],
        'weights': [0.05, 0.07, 0.105],
        'values': [3.254, 4.500001, 7.3221],
        'measure_dates': ['2018-05-05', '2018-05-06', '2018-07-01']
    }
}

df = pd.concat(
    {k: pd.DataFrame(v) for k, v in data.items()}, 
    names=['hash', 'obs']
)

print(df)
                        ids  weights    values measure_dates
hash          obs                                           
IRR-99876-UTY 0     9912234    0.090  2.312200    2021-10-14
              1     9912237    0.090  2.312190    2021-10-15
              2    45555889    0.113  2.739440    2022-12-17
IRR-10881-CKZ 0    45557231    0.310  5.221001    2022-12-31
IRR-881-CKZ   0       24661    0.050  3.254000    2018-05-05
              1       24662    0.070  4.500001    2018-05-06
              2       29431    0.105  7.322100    2018-07-01

现在我们的数据已经清理完毕,我们可以解决您的问题了。

解决您的问题

  1. 最常测量哪些哈希
    1. 哪些散列具有两个值之间的平均值。
    • 这是一个 groupby 操作,我们从每个唯一“散列”的“值”列计算平均值。从那里我们可以使用 Series.between 方法来检查这些平均值是否存在于两个任意值之间。
    # Which hash(es) are measured the most often.
    df.index.get_level_values('hash').value_counts()
    
    # IRR-99876-UTY    3
    # IRR-881-CKZ      3
    # IRR-10881-CKZ    1
    # Name: hash, dtype: int64
    
    # ---
    # Which hashes have an average value between two values.
    ## Here you can see that I'm testing whether the average is between 0 and 4
    print(df.groupby('hash')['values'].mean().between(0, 4))
    
    # IRR-10881-CKZ    False
    # IRR-881-CKZ      False
    # IRR-99876-UTY     True
    # Name: values, dtype: bool
    

【讨论】:

    【解决方案3】:

    一种方法是将其完全展平:

    df = pd.DataFrame.from_dict(data, orient='index')
    df = df.explode('ids').explode('values').explode('weights').explode('measure_dates')
    print(df)
    
    
                       ids weights  values measure_dates
    IRR-99876-UTY  9912234    0.09  2.3122    2021-10-14
    IRR-99876-UTY  9912234    0.09  2.3122    2021-10-15
    IRR-99876-UTY  9912234    0.09  2.3122    2022-12-17
    IRR-99876-UTY  9912234    0.09  2.3122    2021-10-14
    IRR-99876-UTY  9912234    0.09  2.3122    2021-10-15
    ...                ...     ...     ...           ...
    IRR-881-CKZ      29431    0.07  7.3221    2018-05-06
    IRR-881-CKZ      29431    0.07  7.3221    2018-07-01
    IRR-881-CKZ      29431   0.105  7.3221    2018-05-05
    IRR-881-CKZ      29431   0.105  7.3221    2018-05-06
    IRR-881-CKZ      29431   0.105  7.3221    2018-07-01
    

    【讨论】:

    • 我不认为这会做我想做的事。我将更新原始帖子,但这没有正确排列数据。列表中项目的索引对应于进行的相同测量。这个选项看起来像是将值的所有排列都用于散列,而不是每个排列都使用相同的索引。对造成的混乱表示歉意,我会更新我的帖子以使其更清楚。
    猜你喜欢
    • 2020-01-18
    • 2021-03-03
    • 2014-10-07
    • 1970-01-01
    • 2016-12-28
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多