首页 > 解决方案 > 逐行从行列表生成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]]

此时我在将这两个列表(第一个用于列S1S5,另一个用于列W1W6)转换为 DataFrame 时遇到困难,其中缺少的元素应该用 NaN 显示。并且到目前为止的操作仅针对一条线路。我需要对超过 1,000,000 行执行相同的操作。

我想我可以创建名为W1throughW6S1throughS5的系列列表,然后逐行附加值。然后在所有系列都准备好后将所有内容转换为 DataFrame。问题实际上是我有 30 W 和 29 S 列,这需要我在整个运行过程中维护 59 个列表,这听起来没有意义......

有没有更好的方法通过逐行读取文本文件并为每行使用输出的两个列表来构建 DataFrame,其中每行的长度可能不同?

谢谢!

标签: pythonpandasdataframe

解决方案


这有效

  1. 了解我如何构建字典的最简单方法之一是熟悉数据框to_dict()格式的各种选项
  2. 我真的看到了一个简单的模式,字符串分为SW两部分,由一个常量字符串分隔。所以使用 are来获取这两个部分
  3. 用于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

推荐阅读