使用 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']
这是我上一个问题的延续问题。 感谢很多人,我可以修改我的代码如下。
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']