【问题标题】:Reading data from non-CSV files从非 CSV 文件中读取数据
【发布时间】:2023-03-04 11:54:01
【问题描述】:

我有一个文本文件中的数据,如下所示:

2,20 12,40 13,100 14,300
15,440 16,10 24,50 25,350
26,2322 27,3323 28,9999 29,2152
30,2622 31,50

我想将这些数据读入 Python 中的两个不同列表中。但是,这不是 CSV 文件。数据是这样读取的: mass1,intensity1 mass2,intensity2 mass3,intensity3...

我应该如何将质量和强度读入两个不同的列表?我试图避免编写此文件以使数据更整洁和/或采用 CSV 格式。

【问题讨论】:

  • 您可以使用split(" ") 获取质量/强度对列表,然后使用split(",") 拆分每一对。
  • 为什么要“避免写这个文件使数据更整洁”??这似乎是个好习惯!

标签: python csv file-io


【解决方案1】:

看起来您可以line.split() 每条线来隔离各个线对,然后使用pair.split(",") 来分隔每对线中的质量和强度。

【讨论】:

    【解决方案2】:
    mass_results = []
    intensity_results = []
    
    with open('in.txt', 'r') as f:
        for line in f:
            for readings in line.split(' '):
                mass, intensity = readings.split(',')
                mass_results.append(int(mass.strip()))
                intensity_results.append(int(intensity.strip()))
    
    print('Mass values:')
    print(mass_results)
    print('Intensity values:')
    print(intensity_results)
    

    产量:

    Mass values:
    [2, 12, 13, 14, 15, 16, 24, 25, 26, 27, 28, 29, 30, 31]
    Intensity values:
    [20, 40, 100, 300, 440, 10, 50, 350, 2322, 3323, 9999, 2152, 2622, 50]
    

    【讨论】:

    • 我收到此错误:AttributeError: 'list' object has no attribute 'strip' ?
    • 您可以一次读取整个文件(即data=f.read()),然后使用data.split(),而不是逐行读取并按空格分隔。不带参数的拆分基于空格拆分。有了这个,我就有mass = [int(x.split(',')[0].strip()) for x in data.split()]intensity = [int(x.split(',')[1].strip()) for x in data.split()]
    • 所以我必须跳过文件的前 25 行,因为我正在使用 for 循环来跳过它们。但是,当我尝试@jkb 方法时,我收到此错误:ValueError:混合迭代和读取方法会丢失数据。你能解释一下原因吗?
    • 回答你的第一个问题:如果你分开阅读,比如2,3,你应该得到两个值。这些单独的值可能会被strip() 剥离。但是,如果您有任何格式错误的条目,例如2,3,4,5,那么拆分它们可能会搞砸脚本。如果您遇到错误,请在拆分之前尝试打印每个或每个读数,以查看可能发生的情况。
    • 数据和我贴的一模一样,我好像找不到你说的错误
    【解决方案3】:

    假设输入文件看起来像

    #this is header
    #this is header
    #this is header
    2,20 12,40 13,100 14,300
    15,440 16,10 24,50 25,350
    26,2322 27,3323 28,9999 29,2152
    30,2622 31,50
    

    你可以使用re

    方法 1

    如果文件很大

    import re
    
    def xy_parser( fname, header_len=3):
        with open( fname) as f:
            for i,line in enumerate(f):
                if i < header_len:
                    continue
                else:
                    yield re.findall( '[0-9]+,[0-9]+', line)
    
    def xy_maker( xy_str):
        return map( float, xy_str.split(',') )
    
    my_xys = []
    for xys in xy_parse( 'xydata.txt'):
        my_xys += [ xy_maker(val) for val in xys  ]
    my_xys 
    #[[2.0, 20.0],
    # [12.0, 40.0],
    # [13.0, 100.0],
    # [14.0, 300.0],
    # [15.0, 440.0],
    # [16.0, 10.0],
    # [24.0, 50.0],
    # [25.0, 350.0],
    # [26.0, 2322.0],
    # [27.0, 3323.0],
    # [28.0, 9999.0],
    # [29.0, 2152.0],
    # [30.0, 2622.0],
    # [31.0, 50.0]]
    

    方法 2

    我还想指出,如果文件不是太大,那就一口气读完

    f = open('xydata.txt', 'r')
    header_len = 3
    for i in xrange(header_len): # skip the header lines
        f.readline()
    data_str = f.read().replace('\n','') # read from current file pos to end of file and replace new line chars
    
    data_xy_str = re.findall( '[0-9]+,[0-9]+', data_str)
    my_xys      = [ xy_maker(xy_str) for xy_str in data_xy_str ]
    # yields the same result as above
    

    【讨论】:

    • 这就是我现在要读取数据的操作:with open(fname, 'r') as f: for j in xrange(25): f.next() data = f.read() 但是这给了我错误:ValueError: Mixing iteration and read methods would lose data. 在我修复此问题之前无法做任何其他事情或测试任何事情。
    • 那是因为你正在调用 .read 而文件对象 f 被视为生成器。尝试用data = list(f) 替换data=f.read() 这将使数据成为行列表。相反,如果您希望将文件数据作为单个字符串执行 data= ' '.join(f)
    • 为什么会这样?什么是列表,什么是生成器?抱歉,我对这些东西很陌生,只是想理解它。感谢您的帮助
    • 为什么会收到值错误:stackoverflow.com/questions/22179974/…(请参阅所选答案)
    【解决方案4】:
    import re
    
    # read the file
    f = open('input.dat','r')
    data = f.read()
    f.close()
    
    # grab mass and intensity values using regex
    m_re = '[0-9]+(?=,[0-9]+)'
    i_re = '(?<=[0-9],)[0-9]+'
    mass = re.findall(m_re,data)
    intensity = re.findall(i_re,data)
    
    # view results
    print "Mass values:", mass
    print "Intensity values:", intensity
    print "(Mass,Intensity):", zip(mass,intensity)
    

    如果您提到的 25 行标题与正则表达式匹配并改变了结果,您可以尝试将上面的文件输入部分替换为:

    # read the file
    f = open('input.dat','r')
    lines = f.readlines()[25:] # ignore first 25 lines
    f.close()
    data = ' '.join(lines)
    

    【讨论】:

    • 嗨 jkb。 :) 你知道它是谁吗?
    猜你喜欢
    • 2014-01-07
    • 2019-09-17
    • 1970-01-01
    • 2019-05-03
    • 1970-01-01
    • 2018-11-12
    • 1970-01-01
    相关资源
    最近更新 更多