关于python:带有额外索引键的FlatDataFrame嵌套列表/数组(用于时间序列)

Flatten DataFrame nested list/array with extra index keys (for time series)

我有一个结构如下的DataFrame。 (这是JSON规范化的结果)

1
2
3
4
5
6
7
mydf

id    colA    colB    ...    colArray
foo   a1      b1             [{'date': '...', 'data1': '...', 'data2': 0.1 ...}, ...]
bar   a2      b2             [{'date': '...', 'data1': '...', 'data2': 0.1 ...}, ...]
fooz  a3      b3             [{'date': '...', 'data1': '...', 'data2': 0.1 ...}, ...]
barz  a4      b4             [{'date': '...', 'data1': '...', 'data2': 0.1 ...}, ...]
  • date是时间戳
  • colArray行中的每个数组具有不同的长度,但是具有完全相同的数组元素结构
  • ['id', 'colA', 'colB']是我想用作唯一索引的列的示例

我想转换这些数据以便将它们用作时间序列。
我想要的输出将是这样的:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
id    colA    colB    ...    date               data1    data2 ... data n
foo   a1      b1             '1st timestamp'   'flex'   0.1
foo   a1      b1             '...'  
...
foo   a1      b1             'last_timestamp'  
bar   a2      b2             '1st timestamp'   'zorg'
bar   a2      b2             '...'  
...  
bar   a2      b2             'last_timestamp'  
fooz  a3      b3             '...'  
fooz  a3      b3             '...'  
...
fooz  a3      b3             '...'  
etc.

这将允许我基于[foo, a1, b1]

等元组来绘制/分析时间序列

在我看来,这与Flatten嵌套的pandas数据帧非常相似,但是公认的答案令人沮丧:JSON / dict数据并未真正处理以生成具有正确数据的DataFrame。

有人对如何实现这一目标有任何建议吗?

第一种方法

使用以下内容,该内容与我想要的内容很接近:

1
2
tmpdf = pd.DataFrame(mydf['colArray'].tolist())
json_normalize(tmpdf[0])

但是有2个问题:

  • 我丢失了要用作唯一标识符的['id', 'colA', 'colB']元组。
  • 我需要对我的tmpdf的每一行执行该操作
  • 第二种方法

    基于将嵌套的JSON数据作为pandas中的数据帧进行访问

    1
    pd.concat(pd.DataFrame.from_dict(tmp_array) for array in mydf['colArray'])

    它为我提供了一个数据框,其中所有数组都经过展平,正确的列名,但是我丢失了对应的键(['id', 'colA', 'colB'])。
    我认为这是正确的方法,但是我无法弄清楚如何保留索引列(以便我可以通过索引列来过滤每个结果时间序列)。

    太糟糕了,没有" json_melt"功能

    第三种方法

    基于此问题,拼合嵌套的pandas数据框。
    我可以保留索引列,但数组元素仍为JSON,索引为[0,1,2,...]。我在处理可变长度时会遇到麻烦(对于较大的列index

    ,它需要很多NA

    参考书目:
    从深度嵌套的JSON创建Pandas DataFrame,但是该解决方案基于原始JSON处理,而我想在现有的DataFrame

    上执行此操作

    将嵌套的JSON数据作为Pandas中的数据帧进行访问。这与我想要的非常接近。

    平面嵌套的pandas数据框结果看起来像我的第一次尝试,但是底层JSON数据并没有真正"矩阵化"到数据框中。

    一种相当复杂且不令人满意的方法

    编辑:这个问题是相同的,但是在发问时,我无法通过搜索找到它。供将来参考?


    使用字典理解,将pop用于提取原始列,将concat用于MulltiIndex

    1
    df = pd.concat({k: pd.DataFrame(array) for k, array in mydf.pop('colArray').items()})

    替代方法是使用参数keys

    1
    df = pd.concat([pd.DataFrame(array) for array in mydf.pop('colArray')], keys=mydf.index)

    然后删除第二个级别,因此可能会删除带有原始DataFramejoin

    1
    df = df.reset_index(level=1, drop=True).join(mydf).reset_index(drop=True)

    样品:

    1
    2
    3
    4
    5
    6
    7
    mydf = pd.DataFrame({'id': ['foo', 'bar', 'fooz', 'barz'], 'colA': ['a1', 'a2', 'a3', 'a4'], 'colB': ['b1', 'b2', 'b3', 'b4'], 'colArray': [[{'date': 's', 'data1': 't', 'data2': 0.1}, {'date': 'd', 'data1': 'r', 'data2': 0.8}], [{'date': 'd', 'data1': 'y', 'data2': 0.1}], [{'date': 'g', 'data1': 'u', 'data2': 0.1}], [{'date': 'h', 'data1': 'i', 'data2': 0.1}]]})
    print (mydf)
         id colA colB                                           colArray
    0   foo   a1   b1  [{'date': 's', 'data1': 't', 'data2': 0.1}, {'...
    1   bar   a2   b2        [{'
    date': 'd', 'data1': 'y', 'data2': 0.1}]
    2  fooz   a3   b3        [{'
    date': 'g', 'data1': 'u', 'data2': 0.1}]
    3  barz   a4   b4        [{'
    date': 'h', 'data1': 'i', 'data2': 0.1}]
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    df = pd.concat({k: pd.DataFrame(array) for k, array in mydf.pop('colArray').items()})
    print (df)
        data1  data2 date
    0 0     t    0.1    s
      1     r    0.8    d
    1 0     y    0.1    d
    2 0     u    0.1    g
    3 0     i    0.1    h

    df = df.reset_index(level=1, drop=True).join(mydf).reset_index(drop=True)
    print (df)
      data1  data2 date    id colA colB
    0     t    0.1    s   foo   a1   b1
    1     r    0.8    d   foo   a1   b1
    2     y    0.1    d   bar   a2   b2
    3     u    0.1    g  fooz   a3   b3
    4     i    0.1    h  barz   a4   b4