使用csv reader Python将某个列中的所有值替换为某些值

时间:2015-02-27 03:47:31

标签: python csv delimiter

这是我之前提出的问题。 感谢很多人,我可以修改我的代码如下。

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"的分隔符到" &#34 ;.具有先前分隔符的Whiel,代码仅用于行[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的结果(下一个(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部分。 你有什么主意吗? 谢谢, 艾萨克

2 个答案:

答案 0 :(得分:2)

N.B。document的第19页讨论了文件格式。这或多或少与样本数据一致。

修改

好的,在考虑了各种评论,其他答案以及阅读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文件中没有标题行,否则为第21行)并在Python中检查它:

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

显示的最后一行是第18行。例如,如果制表符是分隔符,那么您可能会在数据列之间看到\t。将前一行与最后一行进行比较,以查看所使用的分隔符是否存在差异。

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

答案 1 :(得分:1)

当您的文件中包含固定宽度字段时,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']