Odczytać określone kolumny z pliku CSV z modułem CSV?

176

Próbuję przeanalizować plik csv i wyodrębnić dane tylko z określonych kolumn.

Przykład CSV:

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

Staram się uchwycić tylko konkretne kolumny, powiedzmy ID, Name, Zipi Phone.

Kod, na który patrzyłem, doprowadził mnie do przekonania, że ​​mogę wywołać określoną kolumnę za pomocą odpowiadającego jej numeru, więc np .: Namebędzie odpowiadać 2i iterowanie przez każdy wiersz przy użyciu row[2]spowoduje wyświetlenie wszystkich elementów w kolumnie 2. Tylko tak nie jest.

Oto, co zrobiłem do tej pory:

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

i spodziewam się, że to wydrukuje tylko określone kolumny, które chcę dla każdego wiersza, z wyjątkiem tego, że nie, otrzymuję tylko ostatnią kolumnę.

frankV
źródło
1
dlaczego 'rb'flaga open()? czy nie powinno to być proste r?
Elazar
7
@Elazar: w Pythonie 2 (którego używa OP) "rb"jest odpowiednie do przekazania csv.reader.
DSM
Dlaczego Twój przykładowy plik CSV pokazuje pionową kreskę jako separator, ale przykładowy kod używa spacji?
Kelly S. Francuski
1
@ KellyS.French Pomyślałem, że pomoże to w wizualizacji danych do celów tego pytania.
frankV

Odpowiedzi:

187

Jedynym sposobem, by być coraz ostatnią kolumnę z tym kodem jest, jeśli nie zawierają swoje oświadczenie druku w swojej forpętli.

To najprawdopodobniej koniec twojego kodu:

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

Chcesz, żeby tak było:

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

Skoro już omówiliśmy Twój błąd, chciałbym poświęcić ten czas na wprowadzenie do modułu pandy .

Pandy są spektakularne do radzenia sobie z plikami csv, a poniższy kod wystarczy, aby odczytać plik csv i zapisać całą kolumnę w zmiennej:

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

więc jeśli chcesz zapisać wszystkie informacje w swojej kolumnie Namesw zmiennej, to wszystko, co musisz zrobić:

names = df.Names

To świetny moduł i sugeruję, żebyś się z nim zapoznał. Jeśli z jakiegoś powodu twoja instrukcja print była forzapętlona i nadal drukowała tylko ostatnią kolumnę, co nie powinno się zdarzyć, ale daj mi znać, jeśli moje założenie było błędne. Twój opublikowany kod zawiera wiele błędów związanych z wcięciami, więc trudno było wiedzieć, co powinno być gdzie. Mam nadzieję, że to było pomocne!

Ryan Saxe
źródło
1
Czy można usunąć numery indeksowe z zapytania? @Ryan Saxe
Malachi Bazar
Tak, po prostu powtórz to w pętli for.
davegallant
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'])

Z plikiem takim jak

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

Wyjdzie

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

Lub alternatywnie, jeśli chcesz numeryczne indeksowanie kolumn:

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']

Aby zmienić separator, dodaj delimiter=" "do odpowiedniej instancji, tjreader = csv.reader(f,delimiter=" ")

HennyH
źródło
30

Użyj pand :

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

Odrzuć niepotrzebne kolumny w czasie analizy:

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

PS Po prostu podsumowuję to, co powiedzieli inni w prosty sposób. Rzeczywiste odpowiedzi pochodzą stąd i tutaj .

VasiliNovikov
źródło
1
Myślę, że Pandy to całkowicie akceptowalne rozwiązanie. Często korzystam z Pand i bardzo lubię tę bibliotekę, ale to pytanie odnosiło się konkretnie do modułu CSV.
frankV
1
@frankV Cóż, tytuł, tagi i pierwszy akapit w żaden sposób nie zabraniają pandom, AFAI widzi. Właściwie mam tylko nadzieję, że dodam prostszą odpowiedź do tych, które już zostały tutaj podane (inne odpowiedzi również używają pand).
VasiliNovikov
18

Z pandy można skorzystać read_csvz usecolsparametru:

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

Przykład:

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
ayhan
źródło
16

Możesz użyć numpy.loadtext(filename). Na przykład, jeśli to jest Twoja baza danych .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 |

I chcesz Namekolumny:

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')

Łatwiej możesz użyć genfromtext:

b = np.genfromtxt(r'filepath\name.csv', delimiter='|', names=True,dtype=None)
>>> b['Name']
array([' Adam ', ' Carl ', ' Adolf ', ' Den '], 
      dtype='|S7')
GM
źródło
@G Czy ma być r obok „ścieżka_pliku \ nazwa.csv”?
114
6

Kontekst: Do tego typu pracy powinieneś używać niesamowitej biblioteki Python petl. Pozwoli Ci to zaoszczędzić wiele pracy i potencjalnej frustracji związanej z robieniem rzeczy „ręcznie” za pomocą standardowego modułu csv. AFAIK, jedynymi osobami, które nadal korzystają z modułu csv są ci, którzy nie odkryli jeszcze lepszych narzędzi do pracy z danymi tabelarycznymi (pandy, petl itp.), Co jest w porządku, ale jeśli planujesz pracować z dużą ilością danych w Twoja kariera z różnych dziwnych źródeł, nauka czegoś takiego jak petl jest jedną z najlepszych inwestycji, jakie możesz poczynić. Rozpoczęcie powinno zająć tylko 30 minut po zakończeniu instalacji pip petl. Dokumentacja jest doskonała.

Odpowiedź: Załóżmy, że masz pierwszą tabelę w pliku csv (możesz również załadować ją bezpośrednio z bazy danych za pomocą petla). Następnie po prostu załaduj go i wykonaj następujące czynności.

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')
PeteBeat
źródło
4

Myślę, że jest łatwiejszy sposób

import pandas as pd

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

Więc tutaj iloc[:, 0], :oznacza wszystkie wartości, 0oznacza pozycję kolumny. w poniższym przykładzie IDzostaną wybrane

ID | Name | Address | City | State | Zip | Phone | OPEID | IPEDS |
10 | C... | 130 W.. | Mo.. | AL... | 3.. | 334.. | 01023 | 10063 |
Nuriddin Kudratov
źródło
Jeśli to działa, proszę, zagłosujcie za, dajcie znać innym :)
Nuriddin Kudratov
3
import pandas as pd 
csv_file = pd.read_csv("file.csv") 
column_val_list = csv_file.column_name._ndarray_values
Hari K
źródło
Będziesz musiał pip install pandaspierwszy
Boris
1

Dzięki sposobowi indeksowania i podzbioru ramki danych pandy, bardzo łatwym sposobem wyodrębnienia pojedynczej kolumny z pliku csv do zmiennej jest:

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

Kilka kwestii do rozważenia:

Powyższy fragment utworzy pandy, Seriesa nie dataframe. Sugestia od ayhan z usecolsbędzie również szybsza, jeśli problemem jest prędkość. Testowanie dwóch różnych podejść przy użyciu %timeitpliku csv o rozmiarze 2122 KB daje wyniki 22.8 msdla metody usecols i 53 msdla mojego sugerowanego podejścia.

I nie zapomnij import pandas as pd

Vestland
źródło
0

Jeśli potrzebujesz przetworzyć kolumny osobno, lubię niszczyć kolumny za pomocą zip(*iterable)wzorca (efektywnie „rozpakuj”). Na przykład:

ids, names, zips, phones = zip(*(
  (row[1], row[2], row[6], row[7])
  for row in reader
))
Robert Jensen
źródło
-1

Aby pobrać nazwę kolumny , zamiast używać readlines (), lepiej użyj readline (), aby uniknąć zapętlenia i odczytu całego pliku i przechowywania go w tablicy.

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

    # get number of columns

    line = csvfile.readline()

    first_item = line.split(',')
Jasne
źródło