Lesen Sie bestimmte Spalten aus einer CSV-Datei mit CSV-Modul?


176

Ich versuche, eine CSV-Datei zu analysieren und die Daten nur aus bestimmten Spalten zu extrahieren.

Beispiel csv:

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

Ich versuche nur bestimmte Spalten zu erfassen, sagen ID, Name, Zipund Phone.

Der Code, den ich mir angesehen habe, hat mich zu der Annahme geführt, dass ich die spezifische Spalte mit der entsprechenden Nummer aufrufen kann, dh: Namewürde 2jeder Zeile entsprechen und durchlaufen, wobei row[2]alle Elemente in Spalte 2 erzeugt würden. Nur nicht.

Folgendes habe ich bisher getan:

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

und ich erwarte, dass dies nur die spezifischen Spalten druckt, die ich für jede Zeile haben möchte, außer es nicht, ich bekomme nur die letzte Spalte.


1
warum 'rb'markieren open()? sollte es nicht einfach sein r?
Elazar

7
@Elazar: In Python 2 (das das OP verwendet) "rb"ist es geeignet, an zu übergeben csv.reader.
DSM

Warum zeigt Ihre Beispiel-CSV-Datei das Pipe-Zeichen als Trennzeichen an, Ihr Beispielcode verwendet jedoch ein Leerzeichen?
Kelly S. French

1
@ KellyS.French Ich dachte, es würde helfen, die Daten für die Zwecke dieser Frage zu visualisieren.
FrankV

Antworten:


186

Die letzte Möglichkeit, die letzte Spalte aus diesem Code zu erhalten, besteht darin, dass Sie Ihre print-Anweisung nicht in Ihre forSchleife aufnehmen.

Dies ist höchstwahrscheinlich das Ende Ihres Codes:

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

Du willst, dass es so ist:

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

Nachdem wir Ihren Fehler behandelt haben, möchte ich mir diese Zeit nehmen, um Ihnen das Pandas- Modul vorzustellen .

Pandas ist spektakulär für den Umgang mit CSV-Dateien. Der folgende Code reicht aus, um eine CSV-Datei zu lesen und eine ganze Spalte in einer Variablen zu speichern:

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

Wenn Sie also alle Informationen in Ihrer Spalte Namesin einer Variablen speichern möchten, müssen Sie Folgendes tun:

names = df.Names

Es ist ein großartiges Modul und ich schlage vor, dass Sie es sich ansehen. Wenn Ihre print-Anweisung aus irgendeinem Grund in einer forSchleife war und immer noch nur die letzte Spalte ausgedruckt wurde, was nicht passieren sollte, aber lassen Sie mich wissen, wenn meine Annahme falsch war. Ihr geposteter Code weist viele Einrückungsfehler auf, sodass es schwierig war zu wissen, was wo sein sollte. Hoffe das war hilfreich!


1
Ist es möglich, die Indexnummern aus der Abfrage zu entfernen? @ Ryan Saxe
Malachi Bazar

Ja, durchlaufen Sie es einfach in einer for-Schleife.
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'])

Mit einer Datei wie

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

Wird ausgegeben

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

Oder alternativ, wenn Sie eine numerische Indizierung für die Spalten wünschen:

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

Um den Begrenzer zu ändern, fügen Sie delimiter=" "der entsprechenden Instanziierung hinzu, d. H.reader = csv.reader(f,delimiter=" ")


30

Verwenden Sie Pandas :

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

Verwerfen Sie nicht benötigte Spalten zur Analysezeit:

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

PS Ich fasse nur zusammen, was andere auf einfache Weise gesagt haben. Aktuelle Antworten finden Sie hier und hier .


1
Ich denke, Pandas ist eine absolut akzeptable Lösung. Ich benutze Pandas oft und mag die Bibliothek sehr, aber diese Frage bezog sich speziell auf das CSV-Modul.
FrankV

1
@frankV Nun, der Titel, die Tags und der erste Absatz verbieten Pandas in keiner Weise, wie AFAI sehen kann. Ich habe eigentlich nur gehofft, den hier bereits gemachten Antworten eine einfachere Antwort hinzufügen zu können (andere Antworten verwenden auch Pandas).
VasiliNovikov

18

Mit Pandas können Sie verwenden , read_csvmit usecolsParametern:

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

Beispiel:

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

Sie können verwenden numpy.loadtext(filename). Zum Beispiel, wenn dies Ihre Datenbank ist .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 |

Und du willst die NameSpalte:

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

Einfacher können Sie verwenden genfromtext:

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

@G Soll neben 'Dateipfad \ name.csv' ein r stehen?
114

6

Kontext: Für diese Art von Arbeit sollten Sie die erstaunliche Python-Petl-Bibliothek verwenden. Das erspart Ihnen viel Arbeit und potenzielle Frustration, wenn Sie die Dinge mit dem Standard-CSV-Modul „manuell“ ausführen. AFAIK, die einzigen Personen, die das CSV-Modul noch verwenden, sind diejenigen, die noch keine besseren Tools für die Arbeit mit tabellarischen Daten (Pandas, Petl usw.) entdeckt haben. Dies ist in Ordnung, aber wenn Sie vorhaben, mit vielen Daten in zu arbeiten Ihre Karriere aus verschiedenen seltsamen Quellen, etwas wie petl zu lernen, ist eine der besten Investitionen, die Sie tätigen können. Der Einstieg sollte nur 30 Minuten dauern, nachdem Sie petl petl installiert haben. Die Dokumentation ist hervorragend.

Antwort: Angenommen, Sie haben die erste Tabelle in einer CSV-Datei (Sie können sie auch mit petl direkt aus der Datenbank laden). Dann würden Sie es einfach laden und Folgendes tun.

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

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

Sie müssen pip install pandaszuerst
Boris

2

Ich denke, es gibt einen einfacheren Weg

import pandas as pd

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

Also hier iloc[:, 0], :bedeutet , dass alle Werte, 0die Stellung der Säule. im folgenden Beispiel IDwird ausgewählt

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

Wenn es funktioniert, Leute, bitte stimmen Sie ab, lassen Sie es andere wissen :)
Nuriddin Kudratov

1

Dank der Art und Weise, wie Sie einen Pandas-Datenrahmen indizieren und unterteilen können, können Sie eine einzelne Spalte aus einer CSV-Datei ganz einfach in eine Variable extrahieren:

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

Ein paar Dinge zu beachten:

Das obige Snippet erzeugt einen Pandas Seriesund nicht dataframe. Der Vorschlag von Ayhan mit usecolswird auch schneller sein, wenn Geschwindigkeit ein Problem ist. Das Testen der beiden unterschiedlichen Ansätze unter Verwendung %timeiteiner 22.8 msCSV- Datei mit einer Größe von 2122 KB ergibt den usecols-Ansatz und 53 msmeinen vorgeschlagenen Ansatz.

Und vergiss nicht import pandas as pd


0

Wenn Sie die Spalten separat verarbeiten müssen, möchte ich die Spalten mit dem zip(*iterable)Muster zerstören (effektiv "entpacken"). Also für Ihr Beispiel:

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

-1

Abzuholen Spaltennamen , anstelle der Verwendung von Leseleitungen () eine bessere Nutzung Readline- () zu vermeiden Loop & das komplette Datei Lesen & sie in dem Array gespeichert werden .

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

    # get number of columns

    line = csvfile.readline()

    first_item = line.split(',')
Durch die Nutzung unserer Website bestätigen Sie, dass Sie unsere Cookie-Richtlinie und Datenschutzrichtlinie gelesen und verstanden haben.
Licensed under cc by-sa 3.0 with attribution required.