1

这是我在 StackOverflow 上的第一个问题,因此始终欢迎有关如何使问题更清晰的建议。

我有一个点数据的 CSV,其结构如下所示:

OBJECTID,CART_ID,SHAPE
1,ABC,"(1.2, -4.5)"
2,ABD,"(3.8, 9.1)"

使用 python 3.5 中的 petl 模块,我试图将 SHAPE 字符串转换为两个单独的浮点对象列。使用我从petl文档中了解到的内容,我应该可以分三个步骤完成。

  1. 打开 CSV:a = petl.fromcsv('file.csv')
  2. 将 SHAPE 从字符串转换为元组:b = petl.convert(a, 'SHAPE', tuple)
  3. 使用 .unpack() 将元组分成两列:c = petl.unpack(b, 'SHAPE', ['LAT', 'LON']

我相信这会产生一个如下所示的 CSV 文件:

OBJECTID,CART_ID,LAT,LON
1,ABC,1.2,-4.5
2,ABD,3.8,9.1

相反, .convert() 产生:

OBJECTID,CART_ID,SHAPE
1,ABC,('(', '1', '.', '2', ',', ' ', '-', '4', '.', '5', ')')

任何有关 a) .convert() 正在做什么或 b) 如何重组 CSV 的帮助将不胜感激。

谢谢你。

完整代码:

import petl
a = petl.fromcsv('file.csv')
petl.look(a)
b = petl.convert(a, 'SHAPE', tuple)
petl.look(b)
c = petl.unpack(b, 'SHAPE', ['LAT', 'LON']
petl.look(c)
4

3 回答 3

1

您没有 petl期望的复合表,您仍然有一个字符串。您需要将其传递给不同的函数才能解释它:

>>> ast.literal_eval('(1, 2)')
(1, 2)

集成ast.literal_eval()到 petl 中作为练习留给读者。

于 2016-12-02T06:32:45.420 回答
0

使用 PETL,您可以只使用捕获和正则表达式:

b = petl.capture(a, 'SHAPE', r'\(\s*([-0-9.]+)\s*,\s*([-0-9.]+)\s*\)', ['LAT', 'LON'])
c = petl.convert(b, ['LAT', 'LON'], float)

这应该检测数字并创建 2 个名为 LAT 和 LON 的新列,但它们将是字符串,因此您可能需要在此之后使用 convert 来浮动。

一个稍微“邪恶”的方法是意识到表达式对于具有两个浮点数的元组是有效的 python,所以你可以说:

b = petl.convert(a, 'SHAPE', eval)
c = petl.unpack(b, 'SHAPE', ['LAT', 'LON'])
于 2016-12-06T17:50:28.507 回答
0

正如 Ignacio 所提到的,您仍然需要拆分字符串数据。这可以使用strip()and来完成split(),或者按照建议使用ast.literal_eval()来安全地评估最后一列的内容。

以下示例利用了这一点。它读取您的 CSV 文件,将最后一列拆分为其组成部分,并创建一个新的输出 CSV 文件:

import csv
import ast

with open('input.csv', newline='') as f_input, open('output.csv', 'w', newline='') as f_output:
    csv_input = csv.reader(f_input)
    csv_output = csv.writer(f_output)
    csv_output.writerow(next(csv_input)[:2] + ['LAT', 'LON'])

    for row in csv_input:
        csv_output.writerow(row[:2] + list(ast.literal_eval(row[2])))

给你一个output.csv样子:

OBJECTID,CART_ID,LAT,LON
1,ABC,1.2,-4.5
2,ABD,3.8,9.1
于 2016-12-02T08:10:39.863 回答