【问题标题】:Reading in ascii data lines with missing cells?读取缺少单元格的 ascii 数据行?
【发布时间】:2017-08-29 04:42:31
【问题描述】:

我有一个包含 3 行数据的 ascii 文件,如下所示:

Timestamp: 00:47:14 SATID 13 VAL1 28 VAL2 227 SIGNAL 37                                     SATID 15 VAL1 22 VAL2 265 SIGNAL 30 SATID 16 VAL1 22 VAL2 265 SIGNAL 30
Timestamp: 00:48:14 SATID 13 VAL1 28 VAL2 227 SIGNAL 37                                     SATID 15 VAL1 22 VAL2 265 SIGNAL nan SATID 16 VAL1 22 VAL2 265 SIGNAL 30
Timestamp: 00:49:14                                     SATID 14 VAL1 22 VAL2 265 SIGNAL 30

(请参阅图片了解原始格式)。 original ascii data format 当我尝试将其读入 Python 时,我收到以下错误:

time,sat1,sat2,sat3,sat4 = np.loadtxt("test1.asc", usecols=(1,9,17,25,33), unpack=True, converters = {1: strpdate2num("%H:%M:%S")})
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
File "/System/Library/Frameworks/Python.framework/Versions/2.7/Extras/lib/python/numpy/lib/npyio.py", line 839, in loadtxt
vals = [vals[i] for i in usecols]
IndexError: list index out of range

有谁知道我该怎么做才能让 Python 忽略空单元格并读取每列中可用的任何数据?

谢谢!

【问题讨论】:

  • 文件中的列具有固定宽度。您可能应该使用 Pandas 中的pd.read_fwf()
  • 嗨,DYZ。不幸的是,这些列的宽度有时会略有不同...
  • 相邻列中的值是否重叠?如果不是(如您的示例中所示),您仍然可以将它们视为固定宽度。
  • DYZ,感谢您的提示。 pd.read_fwf() 的使用你有没有一个例子说明我如何使用这个模块?谢谢!顺便说一句,没有一列重叠,所以我认为可以使用您建议的方法...

标签: python python-3.x csv numpy ascii


【解决方案1】:

不使用numpypandas,让我们看看如何“手动”阅读此内容

首先要认识到时间戳总是在同一个地方,紧随其后的是" SATID ",因此您可以通过.split(' SATID ')[0] 获取该信息。

然后,如果您对其余信息执行.split(' SATID '),您将获得所有必需的信息,然后您可以进一步拆分。

在代码中,这看起来像这样:

raw_data = ["Timestamp: 00:47:14 SATID 13 VAL1 28 VAL2 227 SIGNAL 37                                     SATID 15 VAL1 22 VAL2 265 SIGNAL 30 SATID 16 VAL1 22 VAL2 265 SIGNAL 30",
            "Timestamp: 00:48:14 SATID 13 VAL1 28 VAL2 227 SIGNAL 37                                     SATID 15 VAL1 22 VAL2 265 SIGNAL nan SATID 16 VAL1 22 VAL2 265 SIGNAL 30",
            "Timestamp: 00:49:14                                     SATID 14 VAL1 22 VAL2 265 SIGNAL 30"]

output = []
for line in raw_data:
    if 'SATID' in line:  #making sure it is not an empty line
        timestamp = line.split(' SATID ')[0].split('Timestamp: ')[1].rstrip(' ')
        data = line.split(' SATID ')[1:]
        for record in data:
            if 'VAL1' in record:  #making sure it is not an empty record
                satid = record.split(' VAL1 ')[0]
                val1 = record.split(' VAL1 ')[1].split(' VAL2 ')[0]
                val2 = record.split(' VAL2 ')[1].split(' SIGNAL ')[0]
                signal = record.split(' SIGNAL ')[1].rstrip(' ')
                output.append({'Timestamp':timestamp,
                               'SATID':satid,
                               'VAL1':val1,
                               'VAL2':val2,
                               'SIGNAL':signal})


# output is now a list of dictionaries
for d in output:
    print(d)

【讨论】:

  • 感谢 Edwin... 看起来是一种巧妙的方法。但是,有一个问题:如何才能保留每一列,并且可以将其内容分配给特定变量,例如最初显示的示例? (见:time,sat1,sat2,sat3,sat4 以上)
  • 你可以用'字典列表'做任何你想做的事情,或者你可以在循环时修改做你自己的事情,你可以这样做而不是output.append()。请记住,第一个循环是逐行获取时间戳,第二个循环是在该行中逐个记录。这个例子只是为了让你思考,并且只使用标准函数,你真的应该研究一下 pandas,在其中一个 cmets 中提到过。
【解决方案2】:

由于列边不相交,您可以将文件视为固定宽度文件并使用函数read_fwf。您将必须准备列规范列表 - 指定每列的第一个和最后一个位置的元组列表。这是规范的开始(这很无聊,但你只需要做一次):

specs = [(0,11),(11,20),(20,26),(26,29),(29,33),(33,37),
         (37,42),(42,45),(45,52),(52,55),(55,61),(61,63)]
pd.read_fwf('foo.txt',header=None,colspecs=specs)
#            0         1      2     3     4     5     6      7       8     9   \
#0  Timestamp:  00:47:14  SATID  13.0  VAL1  28.0  VAL2  227.0  SIGNAL  37.0   
#1  Timestamp:  00:48:14  SATID  13.0  VAL1  28.0  VAL2  227.0  SIGNAL  37.0   
#2  Timestamp:  00:49:14    NaN   NaN   NaN   NaN   NaN    NaN     NaN   NaN   

#      10   11  
#0    NaN  NaN  
#1    NaN  NaN  
#2  SATID  1.0 

【讨论】:

    猜你喜欢
    • 2013-01-04
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2013-11-12
    相关资源
    最近更新 更多