python - 逐行从行列表生成DataFrame
问题描述
我有一个非常不规则的文本文件,我正在尝试从中创建一个 Pandas DataFrame。经过大量的杂耍(删除不规则、行、可变标题等)后,我已经根据需要解析了每一行,但在将其转换为 DataFrame 时遇到了麻烦。请注意,每行的长度是可变的,每行中的元素数量可以不同。
输入
15.2' 4.3' 16.9' 4.0', GVW kips= 70.6, 9.5, 14.5, 14.1, 15.8, 16.7
3.2' 10.0' , GVW kips= 30.2, 9.5, 11.3, 12.0
Desired Output DataFrame(注意'
我要去掉的字符,后面的第一个数字GWV kips=
不包含在DataFrame中)
S1 S2 S3 S4 S5 W1 W2 W3 W4 W5 W6
15.2 4.3 16.9 4.0 Nan 9.5 14.5 14.1 15.8 16.7 Nan
3.2 10.0 Nan Nan Nan 30.2 9.5 11.3 12.0 Nan Nan
解析一行
my_string = r"15.2' 4.3' 16.9' 4.0', GVW kips= 70.6, 9.5, 14.5, 14.1, 15.8, 16.7"
my_list = my_string.split("'") #get rid of " ' " characters
my_list = [l.split(',') for l in ','.join(my_list).split(' GVW kips= ')] # split the list into two parts one for "S" columns one for "W" columns
my_list = [list(filter(None, lst)) for lst in my_list] # get rid of '' empty strings
my_list = [[float(j) for j in i] for i in my_list] # convert everything to floats
my_list[1].pop(0) # get rid of first element after GVW kips=
这给了我以下两个列表:
[[15.2, 4.3, 16.9, 4.0], [9.5, 14.5, 14.1, 15.8, 16.7]]
此时我在将这两个列表(第一个用于列S1
到S5
,另一个用于列W1
到W6
)转换为 DataFrame 时遇到困难,其中缺少的元素应该用 NaN 显示。并且到目前为止的操作仅针对一条线路。我需要对超过 1,000,000 行执行相同的操作。
我想我可以创建名为W1
throughW6
和S1
throughS5
的系列列表,然后逐行附加值。然后在所有系列都准备好后将所有内容转换为 DataFrame。问题实际上是我有 30 W 和 29 S 列,这需要我在整个运行过程中维护 59 个列表,这听起来没有意义......
有没有更好的方法通过逐行读取文本文件并为每行使用输出的两个列表来构建 DataFrame,其中每行的长度可能不同?
谢谢!
解决方案
这有效
- 了解我如何构建字典的最简单方法之一是熟悉数据框
to_dict()
格式的各种选项 - 我真的看到了一个简单的模式,字符串分为S和W两部分,由一个常量字符串分隔。所以使用 a
re
来获取这两个部分 - 用于
zip
分类并使构建dict
密钥变得简单
import re, io
import pandas as pd
import numpy as np
inp = """15.2' 4.3' 16.9' 4.0', GVW kips= 70.6, 9.5, 14.5, 14.1, 15.8, 16.7
3.2' 10.0' , GVW kips= 30.2, 9.5, 11.3, 12.0"""
# remove unwanted spaces and quotes
inp = inp.replace("'","").replace(",","")
d = {r:{f"{k}{c+1}":vv
# tokenise into S & W with "GVW kips=" being delimter
for k,v in zip(["S","W"], re.findall("^([\d. ]*)GVW kips= ([\d. ]*)$", s)[0])
# use re.split so multiple spaces are treated as one
for c, vv in enumerate(re.split("[ ]+", str(v)))
}
for r, s in enumerate(inp.split("\n"))}
pd.DataFrame(d).T.replace({"":np.nan})
输出
S1 S2 S3 S4 S5 W1 W2 W3 W4 W5 W6
15.2 4.3 16.9 4.0 NaN 70.6 9.5 14.5 14.1 15.8 16.7
3.2 10.0 NaN NaN NaN 30.2 9.5 11.3 12.0 NaN NaN
推荐阅读
- rust - 如何将一组跟踪订阅者合二为一?
- c - break vs goto:在 C 中的以下 bool 函数中哪个更合适?
- r - split 在 sink() 函数中究竟做了什么?
- javascript - 有条件地将具有相同键但不同值的对象推送到数组以避免键入
- c# - 重新排序通用 BindingList 的元素
- lua - 无法将客户端连接到代理
- laravel - .htaccess 文件中是否需要进行任何更改才能访问 API 路由?
- spring-boot - 部署在多个数据中心的基于 JMS 的 Spring Boot 微服务的最佳方法
- r - 使用分隔符加入列表中的列表
- android - 无法在 Flutter 上的地图上放置 json