如何在CSV文件中转置数据集?

26

例如,我想要改变:

Name,Time,Score
Dan,68,20
Suse,42,40
Tracy,50,38
进入:
Name,Dan,Suse,Tracy
Time,68,42,50
Score,20,40,38

编辑:原问题中错误地使用了“transpose”一词。


3
你尝试过什么?这是作业吗?为什么你想将它从普通的东西转变成奇怪的东西? - John Machin
4
哈哈,我希望回到做作业的时光。 - zr.
9
个人认为在这里使用“转置”一词并不不正确。参见http://en.wikipedia.org/wiki/Transpose。 - chmullig
5
@chmullig:矩阵转置正是OP想要的。"Pivot"不是任何人应该寻找的词。 - John Machin
1
@chmullig:看起来我在“不正确”的“不”字上错过了“在”字...通常我不会被双重否定所困扰;我是那个写not not x而不是bool(x)的人 :-) - John Machin
显示剩余6条评论
7个回答

45

如果整个文件的内容可以一次性载入内存,你可以使用

import csv
from itertools import izip
a = izip(*csv.reader(open("input.csv", "rb")))
csv.writer(open("output.csv", "wb")).writerows(a)
你可以基本上把zip()izip()看作转置操作:
a = [(1, 2, 3),
     (4, 5, 6),
     (7, 8, 9)]
zip(*a)
# [(1, 4, 7),
#  (2, 5, 8),
#  (3, 6, 9)]

izip() 避免了立即复制数据,但基本上会执行相同的操作。


2
如果整个文件无法放入内存,请增加更多的内存。 - John La Rooy
2
顺便说一句,看起来手册需要更新,“如果函数调用中出现语法*expression,则expression必须评估为一个序列”...csv.reader()不评估为一个序列。 - John Machin
1
@Tony:在Python教程中。 - Sven Marnach
1
只要你的所有行都有相同数量的项目,这将起作用。如果您有具有不同列数的行,则转置无意义。 - Sven Marnach
经过调查,发现文件对象存在缓冲和缓存问题。抱歉。 - xApple
显示剩余5条评论

18

input.csv 转移到 output.csv。Pandas 也可以帮助。

import pandas as pd
pd.read_csv('input.csv', header=None).T.to_csv('output.csv', header=False, index=False)

优秀的一行代码。 - Aventinus
救星啊,@anton-tarasenko!我仍然不明白为什么 csv.writerows(my_list) 不能满足我的需求。相反,我必须使用 csv.writerow(my_list) 然后使用您的转置一行代码来将我的一行变成多行。太疯狂了! - Alain

5

与nosklo的回答相同(所有信用归给他),但是适用于python3:

from csv import reader, writer 
with open('source.csv') as f, open('destination.csv', 'w') as fw: 
    writer(fw, delimiter=',').writerows(zip(*reader(f, delimiter=',')))

需要使用open(output_filename, 'w', newline='') as fw或者是双倍行距。 - Bernd Wechner

2
from itertools import izip
from csv import reader, writer

with open('source.csv') as f, open('destination.csv', 'w') as fw:
    writer(fw, delimiter=',').writerows(izip(*reader(f, delimiter=',')))

如果使用Python 2.x,则应在两个文件上使用二进制模式。如果使用Python 3.x,则应在两个文件上使用newline=''。另外:delimiter=','是默认值。 - John Machin

1
如果lines是您原始文本的列表,则应该是这样的。
for i in range(1,len(lines)):
    lines[i] = lines[i].split(',')

new_lines = []
for i in range(len(lines[0])):
    new_lines.append("%s,%s,%s" % (lines[0][i], lines[1][i], lines[2][i]))

或者使用 csv Python 模块 - http://docs.python.org/library/csv.html


0

最简单的方法是:

import numpy as np
import pandas as pd

_mat = pd.read_csv("test.csv")
_mat = _mat[_mat.columns[0:3]].values
_t_mat = np.transpose(_mat)

结果:

  • 输入矩阵为:[[1 2 3] [4 5 6]]
  • 输出为:[[1 4] [2 5] [3 6]]

0

将CSV文件读入pandas数据框中,pandas内置了转置函数,可以按以下方式调用。

import pandas as pd

csv = pd.read_csv("test.csv", skiprows=1)
# use skiprows if you want to skip headers
df_csv = pd.DataFrame(data=csv)
transposed_csv = df_csv.T
print(transposed_csv)

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接