前言
某个科研实验室在进行一项物理实现,实验仪器会输出一个 txt 文本的数据,研究人员需要从这个文本中将数据结构化才能进行进行统计分析。
在为个解析和分析过程中,他们选择了 Python 的 pandas 库来完成这些操作。我们今天来完成这这个 txt 数据的结构化解析。
需求:
- 需要将每条记录为一行数据,同时每行也包括开头的时间。
思路:
- 首先分析,这不是一个典型的 csv 文件,也是一个每行包含一个时间特殊值及后边紧跟一个半结构化的 json 格式。
- 我们需要逐行去处理,处理时用空格将每行分隔为两部分,前部分是时间,后部分为 json,这个我们可以用
pd.json_normalize() 去读取,读取时要先用 eval() 将文本转为 Python 列表对象。 - 读取成 DataFrame 后再追加前部分的时间列。
- 将每行产生的 DataFrame 循环拼接起来,就得到了最终想要的 DataFrame 数据。
二、使用步骤
读入数据
代码如下(示例):
# 数据与需求:
# 数据存储在 txt 文件里,可 下载txt ,由于文件非常大,我们这里截取了部分。下载我们来分析一下数据的格式。
# 我们发现一行就是一条完整的数据,针对单行进行排版格式化,分析如下:
# 某行数据排版后(示意)
'''
11:21:07:320 [
{"id":10670,"x":-4.86,"y":53.95,"radian":3.14,"speed":5.9,"kind":0,"position":[1, 2]},
{"id":10718,"x":3.62,"y":64.84,"radian":3.14,"speed":-0.64,"kind":0,"position":[1, 2]},
{"id":10705,"x":1.26,"y":45.85,"radian":3.14,"speed":14.89,"kind":2,"position":[1, 2]},
{"id":10534,"x":2.36,"y":31.43,"radian":3.14,"speed":-0.19,"kind":2,"position":[1, 2]}
]
'''
# 每行的特征有:
# 开始是一个时间,然后用空格与后边的正式数据分隔
# 正式数据是一个大的列表,列表内的每个元素是一条记录
# 每条记录是一个字典,键值分别代码数据意义和数值
import pandas as pd
# 用上下文管理器打开文件
with open('exp-data.txt') as f:
# 定义一个空 DataFrame 来存放最终的数据
df = pd.DataFrame()
# 对每行进行处理,并将数据合并到 df
for line in f.readlines():
# 拆分时间和记录数据
time, data = line.split(' ')
# 读取每行的记录,统一追加时间列
df_line = pd.json_normalize(eval(data)).assign(time=time)
# 将此行的数据与之前合并好的数据再合并
df = pd.concat([df, df_line])
df
#关于代码逻辑可以看代码的注释。这样我们就得到了所有 DataFrame,可以再对数据进行处理分析。
#以下为一个性能更好的写法:
import pandas as pd
with open('exp-data.txt') as f:
data_list, time_list = [], []
for line in f.readlines():
t, data = line.split(' ')
records = eval(data)
# 将所有记录存入一个列表
data_list.extend(records)
# 将所有记录对应的时间构造为一个列表
time_list.extend([t]*len(records))
# 读取数据
df = pd.DataFrame(data_list)
# 增加列
df['time'] = time_list
df
总结
以上就是今天要讲的内容,本文仅仅简单介绍了pandas的使用,而pandas提供了大量能使我们快速便捷地处理数据的函数和方法。