Leia colunas específicas de um arquivo CSV com o módulo CSV?


176

Estou tentando analisar através de um arquivo csv e extrair os dados de apenas colunas específicas.

Exemplo csv:

ID | Name | Address | City | State | Zip | Phone | OPEID | IPEDS |
10 | C... | 130 W.. | Mo.. | AL... | 3.. | 334.. | 01023 | 10063 |

Eu estou tentando capturar apenas colunas específicas, dizem ID, Name, Zipe Phone.

O código que eu observei me levou a acreditar que posso chamar a coluna específica pelo seu número correspondente, ou seja: Namecorresponderia 2e iteraria através de cada linha usando row[2]produziria todos os itens da coluna 2. Só que não.

Aqui está o que eu fiz até agora:

import sys, argparse, csv
from settings import *

# command arguments
parser = argparse.ArgumentParser(description='csv to postgres',\
 fromfile_prefix_chars="@" )
parser.add_argument('file', help='csv file to import', action='store')
args = parser.parse_args()
csv_file = args.file

# open csv file
with open(csv_file, 'rb') as csvfile:

    # get number of columns
    for line in csvfile.readlines():
        array = line.split(',')
        first_item = array[0]

    num_columns = len(array)
    csvfile.seek(0)

    reader = csv.reader(csvfile, delimiter=' ')
        included_cols = [1, 2, 6, 7]

    for row in reader:
            content = list(row[i] for i in included_cols)
            print content

e espero que isso imprima apenas as colunas específicas que quero para cada linha, exceto que não, recebo apenas a última coluna.


1
por que 'rb'sinalizar para open()? não deveria ser simples r?
— Elazar

7
@ Elazar: no Python 2 (que o OP está usando) "rb"é apropriado para a passagem csv.reader.
— DSM

Por que seu arquivo CSV de exemplo mostra o caractere de pipe como delimitador, mas seu código de exemplo usa um espaço?
— Kelly S. French

1
@ KellyS.French Eu pensei que ajudaria a visualizar os dados para os fins desta pergunta.
— precisa saber é

Respostas:


187

A única maneira de obter a última coluna desse código é se você não incluir sua declaração de impressão em seu forloop.

Provavelmente, este é o fim do seu código:

for row in reader:
    content = list(row[i] for i in included_cols)
print content

Você quer que seja assim:

for row in reader:
        content = list(row[i] for i in included_cols)
        print content

Agora que cobrimos seu erro, gostaria de apresentar esse módulo ao pandas .

O Pandas é espetacular para lidar com arquivos csv, e o código a seguir seria tudo o que você precisa para ler um csv e salvar uma coluna inteira em uma variável:

import pandas as pd
df = pd.read_csv(csv_file)
saved_column = df.column_name #you can also use df['column_name']

portanto, se você deseja salvar todas as informações da sua coluna Namesem uma variável, é tudo o que você precisa fazer:

names = df.Names

É um ótimo módulo e sugiro que você o analise. Se, por algum motivo, sua declaração de impressão estava em forloop e ainda estava imprimindo apenas a última coluna, o que não deveria acontecer, mas deixe-me saber se minha suposição estava errada. Seu código postado possui muitos erros de recuo, portanto, era difícil saber o que deveria estar onde. Espero que isso tenha sido útil!


1
É possível remover os números de índice da consulta? @Ryan Saxe
— Malachi Bazar

Sim, apenas itere-o em um loop for.
— Davegallant 07/07

109
import csv
from collections import defaultdict

columns = defaultdict(list) # each value in each column is appended to a list

with open('file.txt') as f:
    reader = csv.DictReader(f) # read rows into a dictionary format
    for row in reader: # read a row as {column1: value1, column2: value2,...}
        for (k,v) in row.items(): # go over each column name and value 
            columns[k].append(v) # append the value into the appropriate list
                                 # based on column name k

print(columns['name'])
print(columns['phone'])
print(columns['street'])

Com um arquivo como

name,phone,street
Bob,0893,32 Silly
James,000,400 McHilly
Smithers,4442,23 Looped St.

Saída

>>> 
['Bob', 'James', 'Smithers']
['0893', '000', '4442']
['32 Silly', '400 McHilly', '23 Looped St.']

Ou, como alternativa, se você deseja indexação numérica para as colunas:

with open('file.txt') as f:
    reader = csv.reader(f)
    reader.next()
    for row in reader:
        for (i,v) in enumerate(row):
            columns[i].append(v)
print(columns[0])

>>> 
['Bob', 'James', 'Smithers']

Para alterar o deliminador, adicione delimiter=" "à instanciação apropriada, ou seja,reader = csv.reader(f,delimiter=" ")


30

Use pandas :

import pandas as pd
my_csv = pd.read_csv(filename)
column = my_csv.column_name
# you can also use my_csv['column_name']

Descartar colunas desnecessárias no momento da análise:

my_filtered_csv = pd.read_csv(filename, usecols=['col1', 'col3', 'col7'])

PS: Estou apenas agregando o que os outros disseram de uma maneira simples. As respostas reais são obtidas aqui e aqui .


1
Eu acho que o Pandas é uma solução perfeitamente aceitável. Eu uso o Pandas frequentemente e realmente gosto da biblioteca, mas essa pergunta referenciou especificamente o módulo CSV.
— FrankV 23/05

1
@frankV Bem, o título, as tags e o primeiro parágrafo não proíbem pandas de forma alguma, a AFAI pode ver. Na verdade, eu apenas esperava adicionar uma resposta mais simples às já feitas aqui (outras respostas também usam pandas).
— VasiliNovikov

18

Com os pandas você pode usar read_csvcom o usecolsparâmetro:

df = pd.read_csv(filename, usecols=['col1', 'col3', 'col7'])

Exemplo:

import pandas as pd
import io

s = '''
total_bill,tip,sex,smoker,day,time,size
16.99,1.01,Female,No,Sun,Dinner,2
10.34,1.66,Male,No,Sun,Dinner,3
21.01,3.5,Male,No,Sun,Dinner,3
'''

df = pd.read_csv(io.StringIO(s), usecols=['total_bill', 'day', 'size'])
print(df)

   total_bill  day  size
0       16.99  Sun     2
1       10.34  Sun     3
2       21.01  Sun     3

16

Você pode usar numpy.loadtext(filename). Por exemplo, se este é seu banco de dados .csv:

ID | Name | Address | City | State | Zip | Phone | OPEID | IPEDS |
10 | Adam | 130 W.. | Mo.. | AL... | 3.. | 334.. | 01023 | 10063 |
10 | Carl | 130 W.. | Mo.. | AL... | 3.. | 334.. | 01023 | 10063 |
10 | Adolf | 130 W.. | Mo.. | AL... | 3.. | 334.. | 01023 | 10063 |
10 | Den | 130 W.. | Mo.. | AL... | 3.. | 334.. | 01023 | 10063 |

E você quer a Namecoluna:

import numpy as np 
b=np.loadtxt(r'filepath\name.csv',dtype=str,delimiter='|',skiprows=1,usecols=(1,))

>>> b
array([' Adam ', ' Carl ', ' Adolf ', ' Den '], 
      dtype='|S7')

Mais facilmente você pode usar genfromtext:

b = np.genfromtxt(r'filepath\name.csv', delimiter='|', names=True,dtype=None)
>>> b['Name']
array([' Adam ', ' Carl ', ' Adolf ', ' Den '], 
      dtype='|S7')

@G Existe um r ao lado de 'filepath \ name.csv'?
— 114

6

Contexto: Para esse tipo de trabalho, você deve usar a incrível biblioteca python petl. Isso poupará muito trabalho e potencial frustração de fazer as coisas 'manualmente' com o módulo csv padrão. AFAIK, as únicas pessoas que ainda usam o módulo csv são aquelas que ainda não descobriram ferramentas melhores para trabalhar com dados tabulares (pandas, petl etc.), o que é bom, mas se você planeja trabalhar com muitos dados em sua carreira de várias fontes estranhas, aprender algo como petl é um dos melhores investimentos que você pode fazer. Para começar, demore apenas 30 minutos depois de concluir o pip install petl. A documentação é excelente.

Resposta: Digamos que você tenha a primeira tabela em um arquivo csv (você também pode carregar diretamente do banco de dados usando petl). Então você simplesmente carregaria e faria o seguinte.

from petl import fromcsv, look, cut, tocsv 

#Load the table
table1 = fromcsv('table1.csv')
# Alter the colums
table2 = cut(table1, 'Song_Name','Artist_ID')
#have a quick look to make sure things are ok. Prints a nicely formatted table to your console
print look(table2)
# Save to new file
tocsv(table2, 'new.csv')

4

Eu acho que existe uma maneira mais fácil

import pandas as pd

dataset = pd.read_csv('table1.csv')
ftCol = dataset.iloc[:, 0].values

Então aqui iloc[:, 0], :significa todos os valores, 0significa a posição da coluna. no exemplo abaixo IDserá selecionado

ID | Name | Address | City | State | Zip | Phone | OPEID | IPEDS |
10 | C... | 130 W.. | Mo.. | AL... | 3.. | 334.. | 01023 | 10063 |

Se funcionar pessoal, por favor, avise, deixe que os outros saibam :)
— Nuriddin Kudratov

3
import pandas as pd 
csv_file = pd.read_csv("file.csv") 
column_val_list = csv_file.column_name._ndarray_values

Você terá que pip install pandasprimeiro
— Boris

1

Graças à maneira como você pode indexar e agrupar um dataframe do pandas, uma maneira muito fácil de extrair uma única coluna de um arquivo csv para uma variável é:

myVar = pd.read_csv('YourPath', sep = ",")['ColumnName']

Algumas coisas a considerar:

O trecho acima produzirá pandas Seriese não dataframe. A sugestão de ayhan with usecolstambém será mais rápida se a velocidade for um problema. Testar as duas abordagens diferentes usando %timeitum arquivo CSV de 2122 KB de tamanho gera 22.8 msa abordagem usecols e 53 msa minha abordagem sugerida.

E não esqueça import pandas as pd


0

Se você precisar processar as colunas separadamente, eu gostaria de desestruturar as colunas com o zip(*iterable)padrão (efetivamente "descompacte"). Então, para o seu exemplo:

ids, names, zips, phones = zip(*(
  (row[1], row[2], row[6], row[7])
  for row in reader
))

-1

Para buscar o nome da coluna , em vez de usar readlines (), use readline () para evitar loop e ler o arquivo completo e armazená-lo na matriz.

with open(csv_file, 'rb') as csvfile:

    # get number of columns

    line = csvfile.readline()

    first_item = line.split(',')
Ao utilizar nosso site, você reconhece que leu e compreendeu nossa Política de Cookies e nossa Política de Privacidade.
Licensed under cc by-sa 3.0 with attribution required.