看过来
《pandas 教程》 持续更新中,提供建议、纠错、催更等加作者微信: gairuo123(备注:pandas教程)和关注公众号「盖若」ID: gairuo。跟作者学习,请进入 Python学习课程。欢迎关注作者出版的书籍:《深入浅出Pandas》 和 《Python之光》。
某个科研实验室在进行一项物理实现,实验仪器会输出一个 txt 文本的数据,研究人员需要从这个文本中将数据结构化才能进行进行统计分析。在为个解析和分析过程中,他们选择了 Python 的 pandas 库来完成这些操作。我们今天来完成这这个 txt 数据的结构化解析。
数据存储在 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]}
]
'''
每行的特征有:
需求是需要将每条记录为一行数据,同时每行也包括开头的时间。
首先分析,这不是一个典型的 csv 文件,也是一个每行包含一个时间特殊值及后边紧跟一个半结构化的 json 格式。
我们需要逐行去处理,处理时用空格将每行分隔为两部分,前部分是时间,后部分为 json,这个我们可以用 pd.json_normalize() 去读取,读取时要先用 eval() 将文本转为 Python 列表对象。
读取成 DataFrame 后再追加前部分的时间列。
将每行产生的 DataFrame 循环拼接起来,就得到了最终想要的 DataFrame 数据。
根据上文的思路,我们的代码如下:
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
'''
id x y radian speed kind position time
0 10670 -4.86 53.95 3.14 5.90 0 [0.0009240878487156014, 0.004577619098975488] 11:21:07:320
1 10718 3.62 64.84 3.14 -0.64 0 [-0.0007592031866001957, 0.004978871276925129] 11:21:07:320
2 10705 1.26 45.85 3.14 14.89 2 [-0.0003569970411845931, 0.0037965203581998906] 11:21:07:320
...
...
2 10705 1.00 41.26 3.14 15.40 2 [-0.0003038889962766716, 0.0034369689727107296] 11:21:08:438
3 10534 2.35 31.33 3.14 0.02 2 [-0.0005925432614476766, 0.0026526066585667134] 11:21:08:438
'''
关于代码逻辑可以看代码的注释。这样我们就得到了所有 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
我们完成了这个需求。
(完)
更新时间:2024-08-18 16:00:01 标签:pandas python 实验数据 dataframe 解析