29

我是脚本新手。我有一个表 ( Table1.txt),我需要创建另一个表,其中 Table1 的行按列排列,反之亦然。我找到了 Perl 和 SQL 的解决方案,但 Python 没有。

我两天前刚开始学习Python,所以就我所知:

import csv
import sys

with open(sys.argv[1], "rt") as inputfile:
   readinput = csv.reader(inputfile, delimiter='\t')
   with open("output.csv", 'wt') as outputfile:
      writer = csv.writer(outputfile, delimiter="\t")
      for row in readinput:
            values = [row[0], row[1], row[2], row[3]]
            writer.writerow([values])

这只是将列复制为列。我现在想做的是把最后一行写成,writer.writecol([values])但似乎没有这样的命令,而且我还没有找到另一种将行写成列的方法。

4

5 回答 5

38

@Ashwini 的答案是完美的。魔法发生在

zip(*lis)

让我解释一下为什么会这样: zip 需要(在最简单的情况下)两个列表并“压缩”它们:zip([1,2,3], [4,5,6])将变为[(1,4), (2,5), (3,6)]. 因此,如果您将外部列表视为矩阵,而将内部元组视为行,那就是转置(即,我们将行转换为列)。

现在,zip是一个任意数量的函数,因此它可以接受两个以上的参数:

# Our matrix is:
# 1 2 3
# 4 5 6
# 7 8 9

zip([1,2,3], [4,5,6], [7,8,9])

>>> [(1, 4, 7), (2, 5, 8), (3, 6, 9)]

# Now it is
# 1 4 7
# 2 5 8
# 3 6 9

我们面临的问题是,在您的情况下,我们不知道要传递给zip. 但至少,我们已经知道这些论点:它们是lis! lis是一个列表,并且该列表的每个元素也是一个列表(对应于输入文件中的一行数字)。这*只是 Python 告诉函数的方式“请使用后面的任何元素作为参数,而不是事物本身!”

所以

lis = [[1,2,3], [4,5,6]]
zip(*lis)

完全一样

zip([1,2,3], [4,5,6])

恭喜,现在你是 Python 专家了!;-)

于 2012-05-08T22:44:38.420 回答
32

通常转置一系列可迭代对象的解决方案是: zip(*original_list)

样本输入:

1   2   3   4   5
6   7   8   9   10
11  12  13  14  15

程序:

with open('in.txt') as f:
  lis = [x.split() for x in f]

for x in zip(*lis):
  for y in x:
    print(y+'\t', end='')
  print('\n')

输出:

1   6   11  

2   7   12  

3   8   13  

4   9   14  

5   10  15
于 2012-05-08T22:01:28.613 回答
24

既然我们在谈论列、行和转置,也许值得一提numpy

>>> import numpy as np
>>> x = np.array([[1,2,3],[4,5,6],[7,8,9],[10,11,12]])
>>> x
array([[ 1,  2,  3],
       [ 4,  5,  6],
       [ 7,  8,  9],
       [10, 11, 12]])
>>> x.T
array([[ 1,  4,  7, 10],
       [ 2,  5,  8, 11],
       [ 3,  6,  9, 12]])
于 2012-05-08T22:56:43.207 回答
2

只是为了构建@Akavall 答案,如果您想从文件中读取,转置然后再次保存,只需执行以下操作:

from numpy import genfromtxt, savetxt
data = genfromtxt('in.txt')
savetxt('out.txt',data.T)

data.T第三行是数据被转置的地方。

于 2012-05-09T09:10:32.080 回答
1

这是一种方法,为简单起见,假设您只想按顺序打印出对象:

  # lets read all the data into a big 2d array
  buffer = []
  for row in readinput: 
        values = [row[0], row[1], row[2], row[3]]  
        buffer.append(values)       

  # what you have in your code
  for i in range(len(buffer)):
      for j in range(len(buffer[0])):
          print buffer[i][j]

  # this is called a transpose; we have buffer[i][j] to read row then column, 
  #    switch i and j around to do the opposite
  for i in range(len(buffer[0])):
      for j in range(len(buffer)):
          print buffer[j][i]

由于您需要一个数组传递给writer.writerow,您可以这样做

  for i in range(len(buffer[0])):
      writer.writerow([buffer[j][i] for j in range(len(buffer))])
于 2012-05-08T21:59:32.683 回答