Python CSV阅读器检查完整数据

时间:2017-10-16 11:21:14

标签: python-3.x csv

我正在尝试创建一个CSV阅读器,它只包含所有第6,7和8列中的读数数据。

我的数据是一年中的几天降雨量。我的代码有一个例外,但有些数据会在几天内被记录下来。记录数据的天数在row[6]中显示,前几天在第6,7和8列中留空,即使它们已完成。

因此,对于读者,我需要制作一个计数器,首先检查数据是否完整(没有空白)或是否有空白并且是另一个读数的一部分(记录在几天内)或不完整(没有读数)我到目前为止所做的工作如下所示:

datalist = []
def read_complete_data():
    ''' Reads the file'''
    filename = input("Enter file name:") #File must be in the same folder as the directory
    with open(filename, 'r') as fileobj:
    #open file for reading
        reader = csv.reader(fileobj, delimiter = ',')
        next(reader)
    tempList = []
    for row in reader:
        if row[5] == "" and row[6] == "" and row[7] == "" :
            tempList.append(row)
    #Checks if the row is complete
        elif row[5] != "" and row[6] != "" and row[7] != "":
            numDay = int(row[6])

    while numDay > 1:
        datalist.append(tempList[1-numDay])
        numDay -= 1

数据示例:

Product code, Station number, Year, Month, Day, Rainfall, Period, Quality
IDCJAC0009, 70247, 1988, 12, 21, 0, , Y
IDCJAC0009, 70247, 1988, 12, 22, 0, , N
IDCJAC0009, 70247, 1988, 12, 23, 0.2, 1, Y 
IDCJAC0009, 70247, 1988, 12, 24, 0.4, 1, Y
IDCJAC0009, 70247, 1988, 12, 25, , Y
IDCJAC0009, 70247, 1988, 12, 26, 34.8, 2, Y 
IDCJAC0009, 70247, 1988, 12, 27, 30.8, 1, N

如上所述,前两个数据样本是不完整的,因为没有测量它们的周期。可以看出,第5行的数据样本是不完整的,但是下面的样本的测量周期为2意味着第5行实际上是完整的,它只是在2天的跨度而不是单日测量。这是测量2天的示例,但是有更大的示例,其中最多5天被分组到一个测量中。最后一列是数据的质量以及是否是质量检查。它必须是Y才能成为完整的数据。正如我添加的第1行和第2行仍然不完整。但是第7行现在还不完整。

输出:基本上我想要实现的是要读取的CSV文件和要从datalist中删除的不完整数据行。使用这个临时列表,我试图让datalist只包含完整的数据集。

通缉输出:

Product code, Station number, Year, Month, Day, Rainfall, Period, Quality
IDCJAC0009, 70247, 1988, 12, 23, 0.2, 1, Y 
IDCJAC0009, 70247, 1988, 12, 24, 0.4, 1, Y
IDCJAC0009, 70247, 1988, 12, 25, , Y
IDCJAC0009, 70247, 1988, 12, 26, 34.8, 2, Y 

使用下一个(阅读器)行,因为数据的顶行包含标题而不是实际数据。我在想我的问题是因为我如何编写for循环和while循环使用临时列表然后复制回主列表(称为datalist)。可能会有一行代码我错过了它需要它才能工作。

我知道这可能是一个非常令人困惑的问题,可能很难回答,因为这里没有给出数据,但是我的代码和读取CSV文件可能出错的任何帮助都非常感谢。我想我会把问题提到这里,即使解释起来也很困惑。 感谢

1 个答案:

答案 0 :(得分:2)

CSV读取器是Python中的生成器这意味着它们不会比预期读取更多,这是有效的,因为它不需要先将整个CSV存储在内存中。

保持生成器语义并编写一个包含CSV读取器的小型过滤器函数并在运行中更改它的输出是有意义的。

要求是:

  1. 如果当前行中没有读数(Rainfall,Period),请将其保留到下一行有读数的行。
  2. 如果某行似乎无效,请不要输出。
  3. 在下文中,filter_rainfall_data是一个生成器函数(生成器使用yield而不是return),它对需求#1有一点缓冲,而不是yield任何要求#2。

    import csv
    
    def filter_rainfall_data(filename):
        with open(filename, 'r', encoding='UTF-8', newline='') as rows:
            reader = csv.reader(rows, delimiter=',')
    
            # yield header row
            yield next(reader)
            buffer = []
    
            for row in reader:
                # strip whitespace from all values
                row = list(map(str.strip, row))
    
                # any row without read-outs is stored in a buffer
                if row[5] == "" and row[6] == "":
                    buffer.append(row)
                    continue
    
                # any row with proper read-outs is yielded
                if row[5] > "" and row[6] > "":
                    days = int(row[6])
    
                    # yield all previously buffered rows, if necessary
                    yield from buffer[-days - 1:]
    
                    # finally yield the current row itself
                    yield row
                    buffer = []
    

    用法如下:

    filename = input("Enter file name:") 
    
    for row in filter_rainfall_data(filename):
        print(row)
    

    使用您的示例输入为我打印

    ['Productcode', 'Stationnumber', 'Year', 'Month', 'Day', 'Rainfall', 'Period', 'Quality']
    ['IDCJAC0009', '70247', '1988', '12', '23', '0.2', '1', 'Y']
    ['IDCJAC0009', '70247', '1988', '12', '24', '0.4', '1', 'Y']
    ['IDCJAC0009', '70247', '1988', '12', '25', '', '', 'Y']
    ['IDCJAC0009', '70247', '1988', '12', '26', '34.8', '2', 'Y']
    ['IDCJAC0009', '70247', '1988', '12', '27', '30.8', '1', 'N']
    

    如果需要,您可以使用CSV编辑器将其转换为新的CSV文件。

    注意: