Python从CSV创建嵌套列表

时间:2019-06-10 14:14:41

标签: python python-3.x list csv read.csv

我需要将csv文件中的数据导入python到看起来像这样的列表中:

list1 = [[(0, 0), (0, 1), (0, 2)],
         [(1, 0), (1, 1), (1, 2)],
         [(2, 0), (3, 1), (3, 2)]]

这样我就可以访问元素

list1[0] = [(0, 1), (0, 2),(0, 3)]    # type list

list1[0][0] = (0,1)    # type tuple

list1[0][0][0] = 0    #type int

我在csv文件中有整数,可以根据需要进行操作。不需要特定的格式 现在数据位于六列中,没有间隔,或者每行六个整数

我尝试了这段代码,但是没有按我的意愿工作:

import csv

with open('file1.csv', 'r') as f:
  reader = csv.reader(f)
  list1 = list(reader)

print(list1)

2 个答案:

答案 0 :(得分:0)

您需要做更多的工作才能根据需要设置列表格式。

假设您的csv文件每行有六个整数,则可能会这样:

import csv

list1 = []
with open('file1.csv', 'r') as f:
    reader = csv.reader(f)
    for line in reader:
        # split line into pairs of integers
        pairs = [(int(i), int(j)) for i, j 
                 in zip(line[0::2], line[1::2])]
        list1.append(pairs)

编辑:

@gregorio-pedullà要求解释该行中使用的索引编制

pairs = [(int(i), int(j)) for i, j 
         in zip(line[0::2], line[1::2])]

在Python中切片序列时,语法为sequence[start:stop:step]。如果省略stop,则切片将自动在序列末尾停止。

所以line[0::2]的意思是“从第一个项目(索引0)开始,然后再取其他所有项目,直到列表末尾。”简单来说,这将提取所有具有偶数索引的项目。

类似地,line[1::2]的意思是“从第二项开始,然后每隔一个进行一次,直到列表末尾。”这将提取所有具有奇数索引的项目。

如果您想玩一个例子,请运行以下命令:

example_list = [0, 1, 2, 3, 4, 5]

evens = example_list[0::2]
print(evens)
# [0, 2, 4]

odds = example_list[1::2]
print(odds)
# [1, 3, 5]

print(zip(evens, odds))
# [(0, 1), (2, 3), (4, 5)]

在您的情况下,您想从每行中提取成对的整数。在列表中创建成对的连续项的最简单方法之一是切片偶数索引项和奇数索引项,然后zip

答案 1 :(得分:0)

这里的挑战是您的结构是3维的,但是csv文件最适合2维数据。另一个挑战是,您的最内层由元组组成,而外层是列表。

您可以通过将其作为通用Python对象列表的简单列表来解决这两个难题(即忽略元组定义第3维的事实)。然后,您可以使用如下代码:

import csv, ast
# store some sample data
list1 = [[(0, 0), (0, 1), (0, 2)],
         [(1, 0), (1, 1), (1, 2)],
         [(2, 0), (3, 1), (3, 2)]]

with open('file1.csv', 'w') as f:
    w = csv.writer(f)
    w.writerows(list1)

# read the sample data
with open('file1.csv', 'r') as f:
    r = csv.reader(f)
    list2 = [
        [ast.literal_eval(t) for t in row]
        for row in r
    ]

list2 == list1
# True

请注意,最里面的对象将被存储为元组的字符串表示形式。然后,在读回它们时,ast.literal_eval将它们转换回元组。

或者,我强烈建议规范化数据表示形式,例如,在csv文件的每一行中存储一对(x,y)对以及它们的行和列坐标。可以这样做:

import csv

# store some sample data
list1 = [[(0, 0), (0, 1), (0, 2)],
         [(1, 0), (1, 1), (1, 2)],
         [(2, 0), (3, 1), (3, 2)]]

with open('file1.csv', 'w') as f:
    w = csv.writer(f)
    for i, row in enumerate(list1):
        for j, (x, y) in enumerate(row):
            w.writerow([i, j, x, y])

# read the sample data
with open('file1.csv', 'r') as f:
    r = csv.reader(f)
    raw_data = [[int(v) for v in row] for row in r]

# figure out how many rows and columns there are
height = max(i for i, j, x, y in raw_data) + 1
width = max(j for i, j, x, y in raw_data) + 1
# create an empty "array" of the right size
list2 = [[None] * width for r in range(height)]
# fill up the array
for i, j, x, y in raw_data:
    list2[i][j] = (x, y)

list2 == list1
# True

作为另一种选择:听起来您可以自由选择文件结构,因为您不需要以任何特定方式组织csv。在这种情况下,您最好使用二进制或json文件而不是csv,因为csv不太适合存储像您这样的结构化变量。

pickle要简单得多,但是会创建一个二进制文件:

import pickle

# store some sample data
list1 = [[(0, 0), (0, 1), (0, 2)],
         [(1, 0), (1, 1), (1, 2)],
         [(2, 0), (3, 1), (3, 2)]]

with open('file1.p', 'wb') as f:
    pickle.dump(list1, f)

# read the data back
with open('file1.p', 'rb') as f:
    list2 = pickle.load(f)

list1 == list2
# True

json创建了一个更具可读性的文件,但是代码更加混乱。

import json

# store some sample data
list1 = [[(0, 0), (0, 1), (0, 2)],
         [(1, 0), (1, 1), (1, 2)],
         [(2, 0), (3, 1), (3, 2)]]

with open('file1.json', 'w') as f:
    json.dump(list1, f)

# read the data back
with open('file1.json', 'r') as f:
    list2 = json.load(f)
    # convert inner lists to tuples (json doesn't distinguish them)
    list2 = [[tuple(t) for t in row] for row in list2]

list1 == list2
# True