使用 csv reader Python 将特定列中的所有值替换为特定值

Replace all the values in a certain column with certain values using csv reader Python

这是我上一个问题的延续问题。 感谢很多人,我可以修改我的代码如下。

import csv
with open("SURFACE2", "rb") as infile, open("output.txt", "wb") as outfile:
    reader = csv.reader(infile, delimiter=" ")
    writer = csv.writer(outfile, delimiter=" ")
    for row in reader:
        row[18] = "999"                  

        writer.writerow(row)

我只是将分隔符从“\t”更改为“”。使用前一个分隔符时,代码只能工作到行[0],使用“”代码可以工作到行[18]。

15.20000           120.60000 98327      get data information here.  SURFACE DATA FROM ??????????? SOURCE    FM-12 SYNOP                                                                                155.00000         1         0         0         0         0         T         F         F   -888888   -888888      20020601030000 100820.00000   

从上面的数据行来看,行[18]正好在15.20000和120.60000之间。

我不确定这两个值之间会发生什么。也许定界符改变了?但是在视觉上我看不出有什么不同。 有什么方法可以让我知道定界符发生了变化,如果是这样,您是否知道为一个代码处理多个定界符?

任何想法或帮助将不胜感激。

谢谢, 艾萨克


repr(next(infile)) 的结果:

'            15.20000           120.60000 98327      get data information here.  SURFACE DATA FROM ??????????? SOURCE    FM-12 SYNOP                                                                                155.00000         1         0         0         0         0         T         F         F   -888888   -888888      20020601030000 100820.00000      0-888888.00000      0-888888.00000      0-888888.00000      0-888888.00000      0-888888.00000      0-888888.00000      0-888888.00000      0-888888.00000      0-888888.00000      0-888888.00000      0-888888.00000      0-888888.00000      0\n'
'  99070.00000      0    155.00000      0    303.20001      0    297.79999      0      3.00000      0    140.00000      0-888888.00000      0-888888.00000      0-888888.00000      0-888888.00000      0\n'
'-777777.00000      0-777777.00000      0      1.00000      0-888888.00000      0-888888.00000      0-888888.00000      0-888888.00000      0-888888.00000      0-888888.00000      0-888888.00000      0\n'
'      1      0      0\n'
'            55.10000            -3.60000 03154      get data information here.  SURFACE DATA FROM ??????????? SOURCE    FM-12 SYNOP                                                                                 16.00000         1         0         0         0         0         T         F         F   -888888   -888888      20020601030000-888888.00000      0-888888.00000      0-888888.00000      0-888888.00000      0-888888.00000      0-888888.00000      0-888888.00000      0-888888.00000      0-888888.00000      0-888888.00000      0-888888.00000      0-888888.00000      0-888888.00000      0\n'
'-888888.00000      0     16.00000      0    281.20001      0    279.89999      0      0.00000      0      0.00000      0-888888.00000      0-888888.00000      0-888888.00000      0-888888.00000      0\n'
'-777777.00000      0-777777.00000      0      1.00000      0-888888.00000      0-888888.00000      0-888888.00000      0-888888.00000      0-888888.00000      0-888888.00000      0-888888.00000      0\n'
'      1      0      0\n'

正如你所看到的,实际上前四行应该是一行。出于某种原因,整行似乎分为 4 个部分。 你有什么主意吗? 谢谢, 艾萨克

N.B. 文件格式在本 document 的第 19 页讨论。这more-or-less与示例数据一致。

编辑

好的,在考虑了各种评论、附加答案并阅读了 original question 之后,似乎有问题的文件不是 CSV 文件。它是格式为 "little_r" 的天气观测数据,它使用以空格填充的固定宽度字段。可用信息不多,所以我猜测,但每组 4 行似乎包含一个单独的观察结果。从您之前的问题看来,您想更新第一行的第 3 列?其他 3 行将被跳过。然后更新下一组4行的第一行中的第3列,等等,等等

OP 中的示例:

            15.20000           120.60000 98327      get data information here.  SURFACE DATA FROM ??????????? SOURCE    FM-12 SYNOP                                                                                155.00000         1         0         0         0         0         T         F         F   -888888   -888888      20020601030000 100820.00000      0-888888.00000      0-888888.00000      0-888888.00000      0-888888.00000      0-888888.00000      0-888888.00000      0-888888.00000      0-888888.00000      0-888888.00000      0-888888.00000      0-888888.00000      0-888888.00000      0
  99070.00000      0    155.00000      0    303.20001      0    297.79999      0      3.00000      0    140.00000      0-888888.00000      0-888888.00000      0-888888.00000      0-888888.00000      0
-777777.00000      0-777777.00000      0      1.00000      0-888888.00000      0-888888.00000      0-888888.00000      0-888888.00000      0-888888.00000      0-888888.00000      0-888888.00000      0
      1      0      0

第一行的前两列(我猜)是观察的纬度和经度。我不知道第 3 列 98327 是什么,但这是 OP 想要更新的列(基于上一个问题)。

这不是 CSV 文件,所以不要将其作为一个文件处理。相反,因为有固定宽度的字段,我们知道需要更新的字段的偏移量和宽度。根据示例数据,第 3 列占用字符 41-46。因此,要更新数据并写入新文件:

offset_col_3 = 41
length_col_3 = 5

with open('SURFACE2') as infile, open('output.txt', 'w') as outfile:
    for line_no, line in enumerate(infile):
        if line_no % 4 == 0:    # every 4th line starting with the first
            line = '{}{:>5}{}'.format(line[:offset_col_3], 999, line[offset_col_3+length_col_3:])
        outfile.write(line)

原回答

尝试从文件中读取第 20 行(第 [19] 行)(假设 CSV 文件中没有 header 行,否则为第 21 行)并在 Python 中检查它:

with open("SURFACE2") as infile:
    for i in range(20):
        print repr(next(infile))

显示的最后一行是第 18 行。例如,如果制表符是分隔符,那么您可能会在数据列之间看到 \t。比较上一行和最后一行,看使用的分隔符是否有区别。

如果您发现 CSV 文件混合了分隔符,那么您可能需要手动拆分字段。

当您的文件中有固定宽度的字段时,csv 模块不是适合使用的工具。您需要做的是明确使用字段长度来拆分行。例如:

# This would be your whole file
data = "\n".join([
    "abc  def gh i",
    "jk   lm  n  o",
    "p    q   r  s",
])
field_widths = [5, 4, 3, 1]

def fields(line, field_widths):
    pos = 0
    for length in field_widths:
        yield line[pos:pos + length].strip()
        pos += length

for line in data.split("\n"):
    print(list(fields(line, field_widths)))

会给你:

['abc', 'def', 'gh', 'i']
['jk', 'lm', 'n', 'o']
['p', 'q', 'r', 's']