解析混合结构化和非结构化数据

时间:2017-07-24 09:46:34

标签: python csv parsing

我们领域的许多光谱数据,模拟输出文件......都是结构化和非结构化数据的混合。

一个例子是以下文件,其中三个点是 站在中间的其他线路上。

...
...
---------------------------------------------------------------------------------------------------
DGA/MPI-2 Parallel Environment:    4 Molcas's processes are running on   1 node(s) x  4 cores each 
----------------------------------------------------------------------------------------------------
...
...
      Mulliken charges per centre and basis function type
      ---------------------------------------------------

             O1      C2      CR3     O4      CR5     O6      O7      C8      O9      O10     O11     C12
      1s     1.9991  1.9984  2.0000  1.9992  2.0000  1.9986  1.9986  1.9983  1.9993  1.9987  1.9986  1.9983
      2s     1.7994  1.0697  2.0000  1.8080  2.0000  1.8648  1.8692  1.0827  1.7580  1.8781  1.8582  1.0834
      2px    1.9368  0.7559  2.0000  1.9364  2.0000  1.6998  1.6786  0.7228  1.9829  1.6891  1.7016  0.7757
      2pz    1.4406  0.6506  2.0000  1.4297  2.0000  1.7096  1.6791  0.6758  1.4469  1.6580  1.7045  0.6490
      2py    1.7790  0.5652  2.0000  1.7909  2.0000  1.5122  1.5263  0.5719  1.5781  1.4733  1.5474  0.5655
      3s    -0.0040  0.0107  1.9934 -0.0041  1.9932 -0.0093 -0.0095  0.0091 -0.0064 -0.0072 -0.0099  0.0106
      3px   -0.0032  0.0205  1.9939 -0.0031  1.9942 -0.0111 -0.0139  0.0189 -0.0015 -0.0107 -0.0145  0.0460
      3pz   -0.0122 -0.0118  1.9936 -0.0114  1.9936 -0.0077 -0.0073 -0.0072 -0.0102 -0.0070 -0.0076 -0.0035
      3py   -0.0021  0.1446  1.9912  0.0005  1.9919 -0.0113 -0.0112  0.1360 -0.0070 -0.0087 -0.0125  0.1386
      4s     0.0000  0.0000  0.1958  0.0000  0.1914  0.0000  0.0000  0.0000  0.0000  0.0000  0.0000  0.0000
      3d2+   0.0000  0.0000  0.6978  0.0000  0.6939  0.0000  0.0000  0.0000  0.0000  0.0000  0.0000  0.0000
      3d1+   0.0000  0.0000  0.4320  0.0000  0.4423  0.0000  0.0000  0.0000  0.0000  0.0000  0.0000  0.0000

通常必须手动解析某些部分,但是如果到达示例表的开头,则表的大小的所有信息都在手边,使用完成的表读取器会很棒。问题是,我所知道的所有典型读者都不允许给出字节偏移。 (csv模块,熊猫,numpy)

这导致两种可能的解决方法:

  1. 给出线偏移。这意味着被调用的csv阅读器将从头开始读取整个文件,并自行计算换行符。我知道它们通常用C语言实现,但速度非常快,但我认为丢掉可用的信息很难看。
  2. 创建一个字符串并将其作为StringIO对象传递给读者。
  3. 与以下示例代码类似:

    import io
    with open('test.log') as f:
        title = 'Mulliken charges per centre and basis function type'
        for line in f: 
            if title == line.strip():
                break
        f.readline()
    
        known_from_previous_parsing = 18
        mull_charges = ''.join([f.readline() for j in range(known_from_previous_parsing)])
        mull_charges = io.StringIO(mull_charges)
        mull_charges = pd.read_csv(mull_charges, delim_whitespace=True)
    

    第二种方法的问题是,它将表格整体写入内存,抛弃了自动缓冲的所有优点......。 (在你问之前,这不是过早的优化,表格可能变得如此之大,整齐地阅读它们会导致交换。)

    所以我的问题是:python中是否有csv解析工具允许指定字节偏移量。或者问一般情况,我的方法是否正确,我应该如何解决这种结构化和非结构化数据的混合?

2 个答案:

答案 0 :(得分:1)

不能告诉熊猫,但使用csv模块,您可以推进文件指针(使用readline()next()),直到您在...之前表格数据的第一行,然后像任何普通的csv文件一样继续(假设您在表格数据之后没有更多的非结构化文本):

offset.dat

This is useles
This is useles
This is useles

Data:
AAA,42
BBB,56
CCC,8878

Python shell:

>>> import csv
>>> f = open("offset.dat")
>>> line = f.next()
>>> while not line.startswith("Data:"):
...     line = f.next()
... 
>>> line
'Data:\n'
>>> r = csv.reader(f)
>>> r.next()
['AAA', '42']
>>> r.next()
['BBB', '56']
>>> r.next()
['CCC', '8878']

答案 1 :(得分:1)

Pandas足够聪明地处理这个问题,假设这个内容位于文件的末尾。使用skiprows参数。

>>> import pandas as pd
>>> df = pd.read_csv('temp.txt', sep='\s+',skiprows=10)
>>> df
          O1      C2     CR3      O4     CR5      O6      O7      C8      O9  \
1s    1.9991  1.9984  2.0000  1.9992  2.0000  1.9986  1.9986  1.9983  1.9993   
2s    1.7994  1.0697  2.0000  1.8080  2.0000  1.8648  1.8692  1.0827  1.7580   
2px   1.9368  0.7559  2.0000  1.9364  2.0000  1.6998  1.6786  0.7228  1.9829   
2pz   1.4406  0.6506  2.0000  1.4297  2.0000  1.7096  1.6791  0.6758  1.4469   
2py   1.7790  0.5652  2.0000  1.7909  2.0000  1.5122  1.5263  0.5719  1.5781   
3s   -0.0040  0.0107  1.9934 -0.0041  1.9932 -0.0093 -0.0095  0.0091 -0.0064   
3px  -0.0032  0.0205  1.9939 -0.0031  1.9942 -0.0111 -0.0139  0.0189 -0.0015   
3pz  -0.0122 -0.0118  1.9936 -0.0114  1.9936 -0.0077 -0.0073 -0.0072 -0.0102   
3py  -0.0021  0.1446  1.9912  0.0005  1.9919 -0.0113 -0.0112  0.1360 -0.0070   
4s    0.0000  0.0000  0.1958  0.0000  0.1914  0.0000  0.0000  0.0000  0.0000   
3d2+  0.0000  0.0000  0.6978  0.0000  0.6939  0.0000  0.0000  0.0000  0.0000   
3d1+  0.0000  0.0000  0.4320  0.0000  0.4423  0.0000  0.0000  0.0000  0.0000   

         O10     O11     C12  
1s    1.9987  1.9986  1.9983  
2s    1.8781  1.8582  1.0834  
2px   1.6891  1.7016  0.7757  
2pz   1.6580  1.7045  0.6490  
2py   1.4733  1.5474  0.5655  
3s   -0.0072 -0.0099  0.0106  
3px  -0.0107 -0.0145  0.0460  
3pz  -0.0070 -0.0076 -0.0035  
3py  -0.0087 -0.0125  0.1386  
4s    0.0000  0.0000  0.0000  
3d2+  0.0000  0.0000  0.0000  
3d1+  0.0000  0.0000  0.0000  

如果它不是,并且您知道或可以计算表格中的行数,那么您仍然可以将此类脚本与rows参数一起使用。

一旦你用pandas读取了这个表,就可以将它发送到csv,sql db,excel等。