使用额外的索引键展平 DataFrame 嵌套列表/数组(对于时间序列)

2024-03-20

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

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']是我想用作唯一索引的列的示例

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

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]

对我来说,这看起来非常相似展平嵌套的 pandas 数据框 https://stackoverflow.com/questions/38574596/flatten-nested-pandas-dataframe,但接受的答案令人沮丧:JSON/dict 数据并未真正处理以生成具有正确数据的 DataFrame。


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


第一种方法

使用以下内容,这接近我想要的:

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

但有两个问题:

  1. 我失去了['id', 'colA', 'colB']我想用作唯一标识符的元组。
  2. 我需要对 tmpdf 的每一行执行操作

第二种方法

基于在 Pandas 中将嵌套 JSON 数据作为数据帧访问 https://stackoverflow.com/questions/23208197/accessing-nested-json-data-as-dataframes-in-pandas

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

它给了我一个数据框,其中所有数组都被展平,列名称正确,但我丢失了相应的键(['id', 'colA', 'colB'])。 我觉得这是正确的方法,但我不知道如何保留索引列(以便我可以通过索引列过滤每个结果时间序列)。

太糟糕了,没有“json_melt”功能

第三种方法

基于这个问题展平嵌套的 pandas 数据框 https://stackoverflow.com/questions/38574596/flatten-nested-pandas-dataframe。 我可以保留索引列,但数组元素仍为 JSON 格式并索引为 [0, 1, 2, ...]。我在处理可变长度时会遇到麻烦(列索引的较高值有很多 NA


参考书目:从深度嵌套的 JSON 创建 Pandas DataFrame https://stackoverflow.com/questions/21494030/create-a-pandas-dataframe-from-deeply-nested-json但解决方案是基于原始的 JSON 处理,而我想在现有的 DataFrame 上执行此操作

在 Pandas 中将嵌套 JSON 数据作为数据帧访问 https://stackoverflow.com/questions/23208197/accessing-nested-json-data-as-dataframes-in-pandas这非常接近我想要的。

展平嵌套的 pandas 数据框 https://stackoverflow.com/questions/38574596/flatten-nested-pandas-dataframe结果看起来像我的第一次尝试,但底层 JSON 数据并未真正“矩阵”到数据帧中。

一种相当复杂且不令人满意的方法 https://dataideas.blog/2018/10/09/loading-json-it-looks-simple-part-1/

EDIT: 这个问题是一样的 https://stackoverflow.com/questions/49671693/pandas-dataframe-normalize-one-json-column-and-merge-with-other-columns但在询问时,我无法通过搜索找到它。供将来参考?


使用字典理解pop http://pandas.pydata.org/pandas-docs/stable/generated/pandas.DataFrame.pop.html用于提取原始列和concat http://pandas.pydata.org/pandas-docs/stable/generated/pandas.concat.html for MulltiIndex:

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

替代方法是使用参数keys:

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

然后删除第二层,这样就可以了join http://pandas.pydata.org/pandas-docs/stable/generated/pandas.DataFrame.join.html与原件DataFrame:

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

Sample:

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}]

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
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

使用额外的索引键展平 DataFrame 嵌套列表/数组(对于时间序列) 的相关文章

随机推荐