【问题标题】:Accessing an array that is in a list that is a value in a dictionary?访问列表中的数组,该数组是字典中的值?
【发布时间】:2020-08-06 00:10:19
【问题描述】:

我有一个包含一些时间序列数据的大型嵌套字典,我的目标是提取这些时间序列数据。我能够进行一些基本的字典导航,但是所有这些不同的数据类型彼此之间真的让我很失望。这是一个带有嵌套字典的 MWE,其中包含来自 2 个不同监测站点的日期时间数据和降水数据。最终,我想将它们与任意数量的监控站点一起绘制。

在这里,我尽我所能将字典中的数据放入一个 numpy 数组,然后放入一个 pandas 数据框。但是,您会看到,数据框每个站点有一行,一列包含每个站点的 precip 数组。我希望它显示与数据值相同的列数。这是实现目标的最佳方式吗?如果是,如何更改列数?

import numpy as np
import pandas as pd

no_stations = 2
my_dict = {
    "UNITS":{
        "precipitation":"Inches"
        },
        "STATION": [
            {'STATUS': 'ACTIVE',
             'NAME' : 'STATION 1',
             'ELEVATION': '758',
             'OBSERVATIONS': {'date_time': [
                '2020-04-13T13:00:00Z', '2020-04-13T14:00:00Z', '2020-04-13T15:00:00Z',
                '2020-04-13T16:00:00Z', '2020-04-13T17:00:00Z', '2020-04-13T18:00:00Z',
                '2020-04-13T19:00:00Z', '2020-04-13T20:00:00Z', '2020-04-13T21:00:00Z',
                '2020-04-13T22:00:00Z', '2020-04-13T23:00:00Z', '2020-04-14T00:00:00Z',
                '2020-04-14T01:00:00Z', '2020-04-14T02:00:00Z', '2020-04-14T03:00:00Z',
                '2020-04-14T04:00:00Z', '2020-04-14T05:00:00Z', '2020-04-14T06:00:00Z',
                '2020-04-14T07:00:00Z', '2020-04-14T08:00:00Z', '2020-04-14T09:00:00Z',
                '2020-04-14T10:00:00Z', '2020-04-14T11:00:00Z', '2020-04-14T12:00:00Z',
                '2020-04-14T13:00:00Z', '2020-04-14T14:00:00Z', '2020-04-14T15:00:00Z',
                '2020-04-14T16:00:00Z', '2020-04-14T17:00:00Z', '2020-04-14T18:00:00Z'],
            'precip_accum_set_1': [
                 0.0, 0.0, 0.0, 0.254, 1.27, 2.794, 4.064, 5.588, 6.858, 8.89, 10.922,
                 12.192, 12.954, 13.716, 15.24, 18.034, 18.288, 18.288, 18.288, 20.32,
                 22.606, 24.892, 25.908, 26.924, 27.432, 27.686, 27.686,
                 27.686, 27.686, 27.94]}},
            {'STATUS': 'ACTIVE',
             'NAME' : 'STATION 2',
             'ELEVATION': '500',
             'OBSERVATIONS': {'date_time': [
                '2020-04-13T13:00:00Z', '2020-04-13T14:00:00Z', '2020-04-13T15:00:00Z',
                '2020-04-13T16:00:00Z', '2020-04-13T17:00:00Z', '2020-04-13T18:00:00Z',
                '2020-04-13T19:00:00Z', '2020-04-13T20:00:00Z', '2020-04-13T21:00:00Z',
                '2020-04-13T22:00:00Z', '2020-04-13T23:00:00Z', '2020-04-14T00:00:00Z',
                '2020-04-14T01:00:00Z', '2020-04-14T02:00:00Z', '2020-04-14T03:00:00Z',
                 '2020-04-14T04:00:00Z', '2020-04-14T05:00:00Z', '2020-04-14T06:00:00Z',
                '2020-04-14T07:00:00Z', '2020-04-14T08:00:00Z', '2020-04-14T09:00:00Z',
                '2020-04-14T10:00:00Z', '2020-04-14T11:00:00Z', '2020-04-14T12:00:00Z',
                '2020-04-14T13:00:00Z', '2020-04-14T14:00:00Z', '2020-04-14T15:00:00Z',
                '2020-04-14T16:00:00Z', '2020-04-14T17:00:00Z', '2020-04-14T18:00:00Z'],
            'precip_accum_set_1': [
                49.53, 49.53, 49.53, 50.038, 51.054, 52.324,53.594, 54.864, 56.134,
                59.944, 61.214, 61.722,62.484, 64.008, 66.802, 67.056, 67.056, 67.31,
                69.088, 71.628, 74.168, 75.184, 75.946, 76.454,76.708,
                76.708, 76.708, 76.708, 76.708]}}
                ]
            }


for key, value in my_dict.items():
    print(key)
    print(type(value))

precip = np.empty([no_stations], dtype=object)
dates = np.empty([no_stations], dtype=object)

for ii in range(no_stations):
    precip[ii] = my_dict['STATION'][ii]['OBSERVATIONS']['precip_accum_set_1']
    dates[ii] = my_dict['STATION'][ii]['OBSERVATIONS']['date_time']
    precip[ii] = np.array(precip[ii], dtype = float)
    dates[ii] = np.array(dates[ii], dtype = str)

df = pd.DataFrame(precip)
print(df)

【问题讨论】:

  • 请发布您的预期输出

标签: python pandas dictionary nested


【解决方案1】:

以下代码输出与数据值具有相同列数的数据帧,如果我误解了您的目标数据帧格式,请告诉我:

# code as in your question


precip = [my_dict['STATION'][ii]['OBSERVATIONS']['precip_accum_set_1'] for ii in range(no_stations)]
dates = [my_dict['STATION'][ii]['OBSERVATIONS']['date_time'] for ii in range(no_stations)]

precip_df = pd.DataFrame(precip)
print(precip_df)

dates_df = pd.DataFrame(dates)
print(dates_df)

输出:

precip_df:
      0      1      2       3       4   ...      25      26      27      28     29
0   0.00   0.00   0.00   0.254   1.270  ...  27.686  27.686  27.686  27.686  27.94
1  49.53  49.53  49.53  50.038  51.054  ...  76.708  76.708  76.708  76.708    NaN

[2 rows x 30 columns]

dates_df:
                      0  ...                    29
0  2020-04-13T13:00:00Z  ...  2020-04-14T18:00:00Z
1  2020-04-13T13:00:00Z  ...  2020-04-14T18:00:00Z

[2 rows x 30 columns]

【讨论】:

    【解决方案2】:

    所有电台特定的数据都在my_dict['STATION'] 内部,其中包含每个电台的字典,每个电台都有一个'OBSERVATIONS' 键。该键下字典中的值具有时间序列值,包含在两个键下,date_timeprecip_accum_set_1

    要将数据放入数据框中,我们希望访问每个站点的 'OBSERVATIONS' 键。您可以通过列表理解来做到这一点。此列表包含两个字典(每个站点一个),每个都有两个键 date_timeobservations 和 precip_accum_set_1

    my_list = [station['OBSERVATIONS'] for station in my_dict['STATION']]
    

    要将这些中的每一个都放入数据框,您可以使用pd.DataFrame.from_dict

    list_df = [pd.DataFrame.from_dict(d).set_index('date_time') for d in my_list]
    

    如果您想创建包含两个站点的单个数据框,请使用 pd.concat 并将 my_dict['STATION'] 中的站点名称用作 keys

    my_df = pd.concat(list_df, keys=[station['NAME'] for station in my_dict['STATION']], names=['NAME'])
    
    my_df.head()
                                        precip_accum_set_1
    NAME        date_time   
    STATION 1   2020-04-13T13:00:00Z    0.000
                2020-04-13T14:00:00Z    0.000
                2020-04-13T15:00:00Z    0.000
                2020-04-13T16:00:00Z    0.254
                2020-04-13T17:00:00Z    1.270
    
    
    my_df.tail()
                                        precip_accum_set_1
    NAME        date_time   
    STATION 2   2020-04-14T14:00:00Z    76.708
                2020-04-14T15:00:00Z    76.708
                2020-04-14T16:00:00Z    76.708
                2020-04-14T17:00:00Z    76.708
                2020-04-14T18:00:00Z    NaN
    

    根据自己的需要,可以根据需要进行改造:

    1. my_df.T 转置数据得到60 列(一行一列,每个站点/时间组合)
    2. 使用my_df.unstack() 每次返回每站一行和一列
    3. 使用my_df.reset_index(level='NAME').pivot(columns='NAME', values='precip_accum_set_1') 将数据透视为每次一行,每个站一列
    4. 使用pd.to_datetime将索引从字符串转换为日期时间

    注意:您的示例字典对STATION 2date_time (30) 和precip_accum_set_1 (29) 观察值不匹配,这将需要被解决以使示例工作。我添加了一个额外的np.nan 以使示例正常运行,但您应该检查实际数据是否没有导致您的问题。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2015-01-10
      • 1970-01-01
      • 2023-04-04
      • 2021-02-13
      • 1970-01-01
      • 2022-11-29
      • 2015-08-07
      • 1970-01-01
      相关资源
      最近更新 更多