0

我有一个 CSV 文件,我想将其转换为不同的格式。CSV 格式如下:

A_to_B,B_to_C,C_to_D,...
0,2,1,...

即,每个标题由两个变量组成,例如 A 和 B,文件中的每一行都包含一个值,即 0、1 或 2。我正在尝试编写一个 Python 脚本来读取这个 CSV 文件和把它变成这样的格式:

A,B,0
B,C,2
C,D,1
...

换句话说,它将包含标题的第一行拆分为变量(例如,A、B、C、D 等),然后匹配新格式的相应值。有谁知道如何做到这一点?我掌握了一些基础知识,但实际算法我无法正确理解。谢谢你的帮助。

更新#1

这是我记录下来的一些代码,但我没有得到正确的输出:

import csv,sys

reader = csv.reader(open(sys.argv[1], 'rt'), delimiter=',')
headers = reader.next()

data = []

for row in reader:
    line = ','.join(row)
    data.append(line)

for row in data:
    for cols, val in zip(headers, row):
        newRow = cols[0], cols[-1], val
        print newRow

CSV 文件如下所示:

A,B,C
0,2,1
0,1,1

但是,代码的输出看起来像这样,所以我需要一种以正确方式迭代 CSV 文件的方法:

('A', 'A', '0')
('B', 'B', ',')
('C', 'C', '2')
('A', 'A', '0')
('B', 'B', ',')
('C', 'C', '1')

更新#2

如果有人偶然发现这一点,这是我最终得到的代码(没有错误处理或任何东西,但它有效):

#!/usr/bin/python
# -*- coding: utf-8 -*-

import csv,os,sys

reader = csv.reader(open(sys.argv[1], 'rt'), delimiter=',')
headers = reader.next()
i = 1

for row in reader:
    os.system('rm id' + str(i) + '.csv')
    os.system('cat ./seeds >> id' + str(i) + '.csv')
    for srcdest,dist in zip(headers, row):
        sd = srcdest.split('_to_')
        src,dest = sd[0],sd[-1]
        if dist == '0':
            pass
        else:
            f = open('id' + str(i) + '.csv', 'a')
            f.write('{},{},{}\n'.format(src.lower().replace('_',''),dest.lower().replace('_',''),float(dist)))
    i=i+1

f.close()

谢谢大家的帮助!

4

3 回答 3

0
from itertools import izip

with open("myfile.csv") as inf, open("new.csv","w") as outf:
    header = [s.split('_to_') for s in inf.next().split(',')]
    for row in inf:
        nums = (int(s) for s in row.split(','))
        for (_from, _to), num in izip(header, nums):
            outf.write("{},{},{}\n".format(_from, _to, _num))
于 2012-06-04T02:15:53.773 回答
0

读入数据,以便

row1 = ['A_to_B','B_to_C',...]
row2 = [0,2,1,...]

这可以通过简单地打开文件、读取该行并用逗号分隔来完成。您可能还想使用csv标准库中的模块。一旦你有了,你可以做类似的事情:

for srcdest,dist in zip(row1,row2):
    sd = srcdest.split('_')
    src,dest = sd[0],sd[-1]
    f.write('{},{},{}\n'.format(src,dest,dist))

f目标文件在哪里。您也可以使用该csv模块来编写行,但仅编写文件可能更容易。

于 2012-06-04T00:35:40.233 回答
0

这是一种可能性:

>>> header
[u'A_to_B', u'B_to_C', u'C_to_D']
>>> data
[[0, 1, 2], [0, 2, 1], [1, 2, 3]]
>>> for row in data:
...     for cols, val in zip(header, row):
...         newRow = cols[0], cols[-1], val
...         print newRow
(u'A', u'B', 0)
(u'B', u'C', 1)
(u'C', u'D', 2)
(u'A', u'B', 0)
(u'B', u'C', 2)
(u'C', u'D', 1)
(u'A', u'B', 1)
(u'B', u'C', 2)
(u'C', u'D', 3)

如图所示,这假设您有一个包含列名列表的“标题”事物,以及一个包含行列表的“数据”事物。(如果你使用标准库中的 csv 模块,这基本上是你得到的。)它输出一个新的行列表。

在此示例中,我假设所有列名都只是一个字母,因此我可以将它们作为“A_to_B”样式列名的第一个和最后一个字符来访问。如果您的列名长度不同,您可以使用cols.split('_')分隔符拆分并提取两个列名。但这只是一个与您的主要问题相切的字符串解析问题。

编辑以响应您的编辑:

删除你的第一个for循环。来自 csv.reader 的数据已经是你想要的格式;通过做你','.join',你将它重新包装成你不想要的格式。您的第二个 for 循环应该直接在阅读器上进行迭代:

>>> for row in reader:
...     for cols, val in zip(headers, row):
...         newRow = cols[0], cols[-1], val
...         print newRow

另一个问题是您在编辑中发布的数据与原始数据格式不同。您最初说列的形式为“A_to_B”、“B_to_C”等,但在第二个示例中,列只是“A”、“B”、“C”等。您需要解释您是如何打算从原始列名派生新列名。

于 2012-06-04T00:24:56.703 回答