Python import csv para a lista

193

Eu tenho um arquivo CSV com cerca de 2000 registros.

Cada registro possui uma sequência e uma categoria:

This is the first line,Line1
This is the second line,Line2
This is the third line,Line3

Eu preciso ler este arquivo em uma lista que se parece com isso:

data = [('This is the first line', 'Line1'),
        ('This is the second line', 'Line2'),
        ('This is the third line', 'Line3')]

Como importar esse CSV para a lista que eu preciso usar Python?

MorganTN
fonte
2
Em seguida, use csvmódulo: docs.python.org/2/library/csv.html
Furas
4
Se houver uma resposta adequada à sua pergunta, aceite-a.
Maciej Gol 24/03
1
Possível duplicata de Como ler e gravar arquivos CSV com Python?
Martin Thoma 11/01

Respostas:

305

Usando o módulo csv :

import csv

with open('file.csv', newline='') as f:
    reader = csv.reader(f)
    data = list(reader)

print(data)

Resultado:

[['This is the first line', 'Line1'], ['This is the second line', 'Line2'], ['This is the third line', 'Line3']]

Se você precisar de tuplas:

import csv

with open('file.csv', newline='') as f:
    reader = csv.reader(f)
    data = [tuple(row) for row in reader]

print(data)

Resultado:

[('This is the first line', 'Line1'), ('This is the second line', 'Line2'), ('This is the third line', 'Line3')]

Resposta antiga do Python 2, também usando o csvmódulo:

import csv
with open('file.csv', 'rb') as f:
    reader = csv.reader(f)
    your_list = list(reader)

print your_list
# [['This is the first line', 'Line1'],
#  ['This is the second line', 'Line2'],
#  ['This is the third line', 'Line3']]
Maciej Gol
fonte
4
Por que você usa 'rb' em vez de 'r'?
Imrek
5
@DrunkenMaster, bfaz com que o arquivo seja aberto no modo binário, em oposição ao modo de texto. Em alguns sistemas, o modo de texto significa que \nserá convertido em uma nova linha específica da plataforma ao ler ou escrever. Veja documentos .
Maciej Gol
7
Isso não funciona no Python 3.x: "csv.Error: iterator deve retornar cadeias, não bytes (você abriu o arquivo no modo de texto?)" Veja abaixo a resposta que funciona no Python 3.x
Gilbert
2
para economizar alguns segundos na depuração, você provavelmente deve adicionar uma nota para a primeira solução, como "Python 2.x version"
paradite
Como usar sua 1ª solução, mas com apenas algumas colunas do arquivo csv?
Sigur
54

Atualizado para Python 3 :

import csv

with open('file.csv', newline='') as f:
    reader = csv.reader(f)
    your_list = list(reader)

print(your_list)

Resultado:

[['This is the first line', 'Line1'], ['This is the second line', 'Line2'], ['This is the third line', 'Line3']]
seokhoonlee
fonte
Especificar 'r'é o modo padrão, portanto, especificá-lo é desnecessário. Os documentos também mencionam Se csvfile é um objeto de arquivo, ele deve ser aberto com newline = ''.
AMC
44

Pandas é muito bom em lidar com dados. Aqui está um exemplo de como usá-lo:

import pandas as pd

# Read the CSV into a pandas data frame (df)
#   With a df you can do many things
#   most important: visualize data with Seaborn
df = pd.read_csv('filename.csv', delimiter=',')

# Or export it in many ways, e.g. a list of tuples
tuples = [tuple(x) for x in df.values]

# or export it as a list of dicts
dicts = df.to_dict().values()

Uma grande vantagem é que os pandas lidam automaticamente com as linhas do cabeçalho.

Se você nunca ouviu falar de Seaborn , recomendo dar uma olhada.

Consulte também: Como leio e escrevo arquivos CSV com Python?

Pandas # 2

import pandas as pd

# Get data - reading the CSV file
import mpu.pd
df = mpu.pd.example_df()

# Convert
dicts = df.to_dict('records')

O conteúdo de df é:

     country   population population_time    EUR
0    Germany   82521653.0      2016-12-01   True
1     France   66991000.0      2017-01-01   True
2  Indonesia  255461700.0      2017-01-01  False
3    Ireland    4761865.0             NaT   True
4      Spain   46549045.0      2017-06-01   True
5    Vatican          NaN             NaT   True

O conteúdo dos ditados é

[{'country': 'Germany', 'population': 82521653.0, 'population_time': Timestamp('2016-12-01 00:00:00'), 'EUR': True},
 {'country': 'France', 'population': 66991000.0, 'population_time': Timestamp('2017-01-01 00:00:00'), 'EUR': True},
 {'country': 'Indonesia', 'population': 255461700.0, 'population_time': Timestamp('2017-01-01 00:00:00'), 'EUR': False},
 {'country': 'Ireland', 'population': 4761865.0, 'population_time': NaT, 'EUR': True},
 {'country': 'Spain', 'population': 46549045.0, 'population_time': Timestamp('2017-06-01 00:00:00'), 'EUR': True},
 {'country': 'Vatican', 'population': nan, 'population_time': NaT, 'EUR': True}]

Pandas # 3

import pandas as pd

# Get data - reading the CSV file
import mpu.pd
df = mpu.pd.example_df()

# Convert
lists = [[row[col] for col in df.columns] for row in df.to_dict('records')]

O conteúdo de listsé:

[['Germany', 82521653.0, Timestamp('2016-12-01 00:00:00'), True],
 ['France', 66991000.0, Timestamp('2017-01-01 00:00:00'), True],
 ['Indonesia', 255461700.0, Timestamp('2017-01-01 00:00:00'), False],
 ['Ireland', 4761865.0, NaT, True],
 ['Spain', 46549045.0, Timestamp('2017-06-01 00:00:00'), True],
 ['Vatican', nan, NaT, True]]
Martin Thoma
fonte
tuples = [tuple(x) for x in df.values]pode ser escrito em seu tuples = list(df.itertuples(index=False))lugar. Observe que os documentos do Pandas desencorajam o uso de a .valuesfavor de .to_numpy(). O terceiro exemplo é confuso para mim. Primeiro, porque a variável é nomeada tuples, o que implicaria que seja uma lista de tuplas, enquanto na verdade é uma lista de listas. Segundo, porque, até onde eu sei, toda a expressão pode ser substituída por df.to_list(). Também não sei se o segundo exemplo é realmente relevante aqui.
AMC
9

Atualização para Python3:

import csv
from pprint import pprint

with open('text.csv', newline='') as file:
    reader = csv.reader(file)
    res = list(map(tuple, reader))

pprint(res)

Resultado:

[('This is the first line', ' Line1'),
 ('This is the second line', ' Line2'),
 ('This is the third line', ' Line3')]

Se csvfile for um objeto de arquivo, ele deverá ser aberto com newline=''.
módulo csv

Cálculo
fonte
Por que usar list(map())sobre uma lista de compreensão? Observe também o espaço em branco no início de cada elemento da segunda coluna.
AMC
5

Se você tiver certeza não há vírgulas em sua entrada, além de separar a categoria, você pode ler o arquivo linha por linha e dividida em ,, em seguida, empurre o resultado paraList

Dito isso, parece que você está vendo um arquivo CSV, então você pode considerar usar os módulos para ele

Miquel
fonte
4
result = []
for line in text.splitlines():
    result.append(tuple(line.split(",")))
Acid_Snake
fonte
1
Você pode adicionar um pouco de explicação a este post? Código só é (às vezes) bom, mas o código e explicação é (na maioria das vezes) melhor
Barranka
3
Eu sei que o comentário de Barranka tem mais de um ano, mas para quem se depara com isso e não consegue descobrir: para linha em text.splitlines (): coloca cada linha individual na variável temporária "line". line.split (",") cria uma lista de seqüências de caracteres que são divididas na vírgula. tupla (~) coloca essa lista em uma tupla e acrescenta (~) a adiciona ao resultado. Após o loop, o resultado é uma lista de tuplas, com cada tupla uma linha e cada elemento da tupla um elemento no arquivo csv.
Louis
Além do que o @Louis disse, não há necessidade de usar .read().splitlines(), você pode iterar diretamente cada linha do arquivo: for line in in_file: res.append(tuple(line.rstrip().split(",")))Além disso, observe que usar .split(',')significa que cada elemento da segunda coluna começará com espaço em branco extra.
AMC
Adendo ao código que acabei de compartilhar acima: line.rstrip()-> line.rstrip('\n').
AMC
3

Como já foi dito nos comentários, você pode usar a csvbiblioteca em python. csv significa valores separados por vírgula, que parecem exatamente o seu caso: um rótulo e um valor separados por uma vírgula.

Sendo um tipo de categoria e valor, prefiro usar um tipo de dicionário em vez de uma lista de tuplas.

De qualquer forma, no código abaixo, mostro os dois lados: dé o dicionário e lé a lista de tuplas.

import csv

file_name = "test.txt"
try:
    csvfile = open(file_name, 'rt')
except:
    print("File not found")
csvReader = csv.reader(csvfile, delimiter=",")
d = dict()
l =  list()
for row in csvReader:
    d[row[1]] = row[0]
    l.append((row[0], row[1]))
print(d)
print(l)
Francesco Boi
fonte
Por que não usar um gerenciador de contexto para manipular o arquivo? Por que você está misturando duas convenções de nomenclatura de variáveis ​​diferentes? Não é (row[0], row[1])mais fraco / propenso a erros do que apenas o uso tuple(row)?
AMC
Por que você acha que fazer tupla (linha) é menos propenso a erros? A que convenção de nomenclatura variável você está se referindo? Por favor, vincule uma convenção oficial de nomenclatura python. Tanto quanto sei, try -except é uma boa maneira de lidar com arquivos: o que você quer dizer com manipulador de contexto?
Francesco Boi
Por que você acha que fazer tupla (linha) é menos propenso a erros? Porque não requer que você escreva todos os índices manualmente. Se você cometer um erro ou o número de elementos for alterado, será necessário voltar e alterar seu código. A tentativa de exceção é boa, os gerenciadores de contexto são os com declaração. Você pode encontrar muitos recursos sobre o assunto, como este .
AMC
Não vejo como o gerenciador de contexto seria melhor do que o bom bloco try-except. Para o outro, o aspecto positivo é que você digita menos código; para o resto, se o número de elementos (eu acho que você quer dizer o número de colunas) muda o meu é melhor porque está extraindo apenas os valores desejados, enquanto o outro está extraindo todo o excel. Sem nenhum requisito específico, você não pode dizer qual é o melhor, por isso é uma perda de tempo discutindo o que é melhor: nesse caso, ambos são válidos
Francesco Boi
Não vejo como o gerenciador de contexto seria melhor do que o bom bloco try-except. Por favor, veja meu comentário anterior, o gerenciador de contexto não substituirá a tentativa, exceto.
AMC
2

Um loop simples seria suficiente:

lines = []
with open('test.txt', 'r') as f:
    for line in f.readlines():
        l,name = line.strip().split(',')
        lines.append((l,name))

print lines
Hunter McMillen
fonte
1
E se algumas das entradas tiverem vírgulas?
Tony Ennis
@TonyEnnis Então você precisaria usar um loop de processamento mais avançado. A resposta de Maciej acima mostra como usar o analisador csv que acompanha o Python para executar esta operação. Esse analisador provavelmente tem toda a lógica necessária.
Hunter McMillen
1

Infelizmente, acho que nenhuma das respostas existentes é particularmente satisfatória.

Aqui está uma solução Python 3 direta e completa, usando o módulo csv .

import csv

with open('../resources/temp_in.csv', newline='') as f:
    reader = csv.reader(f, skipinitialspace=True)
    rows = list(reader)

print(rows)

Observe o skipinitialspace=Trueargumento. Isso é necessário, pois, infelizmente, o CSV do OP contém espaço em branco após cada vírgula.

Resultado:

[['This is the first line', 'Line1'], ['This is the second line', 'Line2'], ['This is the third line', 'Line3']]
AMC
fonte
0

Estendendo um pouco seus requisitos e assumindo que você não se importa com a ordem das linhas e deseja agrupá-los em categorias, a seguinte solução pode funcionar para você:

>>> fname = "lines.txt"
>>> from collections import defaultdict
>>> dct = defaultdict(list)
>>> with open(fname) as f:
...     for line in f:
...         text, cat = line.rstrip("\n").split(",", 1)
...         dct[cat].append(text)
...
>>> dct
defaultdict(<type 'list'>, {' CatA': ['This is the first line', 'This is the another line'], ' CatC': ['This is the third line'], ' CatB': ['This is the second line', 'This is the last line']})

Dessa forma, você obtém todas as linhas relevantes disponíveis no dicionário, sendo a categoria a chave.

Jan Vlcinsky
fonte
0

Aqui está a maneira mais fácil no Python 3.x de importar um CSV para uma matriz multidimensional e suas únicas 4 linhas de código sem importar nada!

#pull a CSV into a multidimensional array in 4 lines!

L=[]                            #Create an empty list for the main array
for line in open('log.txt'):    #Open the file and read all the lines
    x=line.rstrip()             #Strip the \n from each line
    L.append(x.split(','))      #Split each line into a list and add it to the
                                #Multidimensional array
print(L)
Jason Boucher
fonte
Cuidado, é uma lista, não uma matriz! Por que não usar um gerenciador de contexto para lidar adequadamente com o objeto de arquivo? Observe que essa solução deixa espaço em branco extra no segundo item de cada linha e que falhará se algum dos dados contiver uma vírgula.
AMC
-1

A seguir, é um pedaço de código que usa o módulo csv, mas extrai o conteúdo file.csv para uma lista de dictos usando a primeira linha, que é um cabeçalho da tabela csv

import csv
def csv2dicts(filename):
  with open(filename, 'rb') as f:
    reader = csv.reader(f)
    lines = list(reader)
    if len(lines) < 2: return None
    names = lines[0]
    if len(names) < 1: return None
    dicts = []
    for values in lines[1:]:
      if len(values) != len(names): return None
      d = {}
      for i,_ in enumerate(names):
        d[names[i]] = values[i]
      dicts.append(d)
    return dicts
  return None

if __name__ == '__main__':
  your_list = csv2dicts('file.csv')
  print your_list
Alexey Antonenko
fonte
1
Por que não usar apenas csv.DictReader?
AMC