python - 使用额外的索引键展平 DataFrame 嵌套列表/数组(用于时间序列)
问题描述
我有一个结构如下的 DataFrame。(这是 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]
对我来说,这看起来与Flatten nested pandas dataframe非常相似,但公认的答案令人沮丧:JSON/dict 数据并未真正处理以生成具有正确数据的 DataFrame。
有人对如何实现这一目标有任何建议吗?
第一种方法
使用以下内容,这与我想要的很接近:
tmpdf = pd.DataFrame(mydf['colArray'].tolist())
json_normalize(tmpdf[0])
但是有2个问题:
- 我丢失了
['id', 'colA', 'colB']
我想用作唯一标识符的元组。 - 我需要对 tmpdf 的每一行执行操作
第二种方法
基于在 Pandas 中将嵌套的 JSON 数据作为数据框访问
pd.concat(pd.DataFrame.from_dict(tmp_array) for array in mydf['colArray'])
它为我提供了一个数据框,其中所有数组均已展平,列名正确,但我丢失了相应的键 ( ['id', 'colA', 'colB']
)。我觉得这是正确的方法,但我不知道如何保留索引列(以便我可以通过索引列过滤每个结果时间序列)。
太糟糕了,没有“json_melt”功能
第三种方法
基于这个问题Flatten nested pandas dataframe。我可以保留我的索引列,但数组元素仍然在 JSON 中并且索引为 [0, 1, 2, ...]。我将无法处理可变长度(列索引的较高值有很多 NA
参考书目: 从深度嵌套的 JSON 创建 Pandas DataFrame但解决方案基于原始 JSON 处理,而我想在现有 DataFrame 上执行此操作
在 Pandas 中将嵌套的 JSON 数据作为数据框访问这非常接近我想要的。
展平嵌套的 pandas 数据框结果看起来像是我的第一次尝试,但底层 JSON 数据并没有真正“矩阵化”到数据框中。
编辑: 这个问题是一样的但是在问的时候,我无法通过搜索找到它。供日后参考?
解决方案
将字典理解与pop
for extract original column 和concat
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
使用 original DataFrame
:
df = df.reset_index(level=1, drop=True).join(mydf).reset_index(drop=True)
样品:
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
推荐阅读
- spring-security - Spring Security 中的 hasRole() 和 hasAuthority() 有什么区别
- c# - 页面加载后修改viewbag内容
- python - 无法打开之前打开的 H5
- video-streaming - 带有 iframe 信息的实时 HLS 生成器
- postgresql - 如何正确分组 Postgres 数据
- pandas - 以 pandas 列作为参数调用函数
- excel - VBA - 填充自定义功能区下拉/列表框
- python - 'requests' 导入的模块在 IDLE 上不起作用
- angular - 如何强制 this.gridOption.getRowStyle 函数?
- python - 从表格中排除一些结果-Web Scraping with Python