使用petl将字符串转换为元组

时间:2016-12-02 06:27:36

标签: python python-3.x csv petl

这是我关于StackOverflow的第一个问题,因此欢迎提出如何使问题更清晰的建议。

我的点数据CSV结构如下所示:

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

在python 3.5中使用petl模块,我试图将SHAPE字符串转换为两个独立的float对象列。使用我从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']
  4. 将元组拆分为两列

    我相信这会产生一个如下所示的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)
    

3 个答案:

答案 0 :(得分:1)

你没有像petl expects那样的复合表,你仍然有一个字符串。您需要将其传递给另一个函数才能解释它:

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

ast.literal_eval()整合到petl中是留给读者的练习。

答案 1 :(得分:0)

正如Ignacio所提到的,您仍然需要拆分字符串数据。这可以使用strip()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

答案 2 :(得分:0)

使用PETL,您可以使用capture和正则表达式:

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 to float。

稍微多一点"邪恶"方法是要意识到表达式是一个有两个浮点数的元组的有效python,所以你可以这样说:

b = petl.convert(a, 'SHAPE', eval)
c = petl.unpack(b, 'SHAPE', ['LAT', 'LON'])