CSV modülü ile bir CSV dosyasındaki belirli sütunları okumak?


176

Bir csv dosyası ayrıştırmak ve sadece belirli sütunlardan veri ayıklamak çalışıyorum.

Örnek csv:

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

Ben, sadece belirli sütunları yakalamak söylemeye çalışıyorum ID, Name, Zipve Phone.

Ben baktım kod karşılık gelen sayı ile belirli bir sütun çağırabilir inanıyorum yol açtı, yani yani: Namekarşılık gelen 2ve kullanarak her satır üzerinden yineleme row[2]sütun 2 tüm öğeleri üretecek.

Şimdiye kadar yaptığım şey:

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

ve bunun sadece her satır için istediğim belirli sütunları yazdıracağını beklemiyorum, bunun dışında sadece son sütunu alıyorum.


1
neden 'rb'bayrak open()? basit değil rmi?
Elazar

7
@Elazar: Python 2'de (OP'nin kullandığı) "rb"geçmek için uygundur csv.reader.
DSM

Örnek CSV dosyanız neden kanal karakterini sınırlayıcı olarak gösteriyor ancak örnek kodunuz boşluk kullanıyor?
Kelly

1
@ KellyS.French Bu sorunun amaçları için verilerin görselleştirilmesine yardımcı olacağını düşündüm.
frankV

Yanıtlar:


187

Basılı yayın include ifadesi yoksa bu koddan son sütun almak olacaktır tek yolu içinde senin fordöngü.

Bu büyük olasılıkla kodunuzun sonu:

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

Bunun olmasını istersiniz:

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

Şimdi hatanızı ele aldığımıza göre, sizi panda modülüne tanıtmak için bu zamanı ayırmak istiyorum .

Pandalar csv dosyalarıyla uğraşmak için muhteşemdir ve aşağıdaki kod bir csv'yi okumak ve bir sütunun tamamını bir değişkene kaydetmek için ihtiyacınız olan tek şey olacaktır:

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

sütununuzdaki tüm bilgileri Namesbir değişkene kaydetmek istiyorsanız, tek yapmanız gereken budur:

names = df.Names

Harika bir modül ve içine bakmanızı öneririm. Herhangi bir nedenden ötürü print deyiminiz fordöngüdeyse ve hala son sütunu yazdırıyorsa, bu gerçekleşmemelidir, ancak varsayımımın yanlış olup olmadığını bana bildirin. Gönderilen kodunuzda çok sayıda girinti hatası var, bu yüzden nerede olması gerektiğini bilmek zordu. Umarım bu yardımcı oldu!


1
Dizin numaralarını sorgudan kaldırmak mümkün müdür? @Ryan Saxe
Malachi Bazar

Evet, sadece bir for döngüsü içinde yineleyin.
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'])

Gibi bir dosyayla

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

Çıktı olacak

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

Alternatif olarak, sütunlar için sayısal dizinleme istiyorsanız:

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

Sınırlayıcıyı değiştirmek için delimiter=" "uygun örneğe ekleyin , örn.reader = csv.reader(f,delimiter=" ")


30

Pandaları kullanın :

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

Gereksiz sütunları ayrıştırma zamanında atın:

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

PS: Başkalarının söylediklerini basit bir şekilde bir araya getiriyorum. Gerçek cevaplar buradan ve buradan alınır .


1
Bence Pandalar son derece kabul edilebilir bir çözüm. Pandaları sık sık ve gerçekten kütüphaneyi kullanıyorum, ancak bu soru özellikle CSV modülüne atıfta bulundu.
frankV

1
@frankV Eh, başlık, etiketler ve ilk paragraf pandaları hiçbir şekilde yasaklamıyor, AFAI görebiliyor. Aslında zaten burada yapılanlara daha basit bir cevap eklemeyi umuyorum (diğer cevaplar pandaları da kullanıyor).
VasiliNovikov

18

İle pandalar kullanabilirsiniz read_csvile usecolsparametre:

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

Misal:

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

Kullanabilirsiniz numpy.loadtext(filename). Örneğin, veritabanınız buysa .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 |

Ve Namesütunu istiyorsunuz :

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

Daha kolay kullanabilirsiniz genfromtext:

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

@G 'dosyayolu \ name.csv'nin yanında r olması mı gerekiyor?
114

6

Bağlam: Bu tür çalışmalar için şaşırtıcı python petl kütüphanesini kullanmalısınız. Bu, standart csv modülü ile 'manuel' bir şeyler yapmaktan çok fazla iş ve potansiyel hayal kırıklığını kurtaracaktır. AFAIK, hala csv modülünü kullanan kişiler, henüz seküler verilerle (pandalar, petl, vb.) Çalışmak için daha iyi araçlar bulamayan kişilerdir, ki bu iyi, ancak çok fazla veriyle çalışmayı planlıyorsanız kariyerinizi çeşitli garip kaynaklardan, petl gibi bir şey öğrenmek yapabileceğiniz en iyi yatırımlardan biridir. Başlamak için pip install petl yaptıktan sonra sadece 30 dakika sürmelidir. Dokümantasyon mükemmel.

Cevap: Diyelim ki bir csv dosyasında ilk tablo var (petl kullanarak doğrudan veritabanından da yükleyebilirsiniz). Sonra sadece yüklemek ve aşağıdakileri yapmak.

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

Bence daha kolay bir yol var

import pandas as pd

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

Yani burada iloc[:, 0], :tüm değerler, 0sütunun konumu anlamına gelir. aşağıdaki örnekte IDseçilecektir

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

Çalışıyorsa, lütfen oy verin, başkalarına bildirin :)
Nuriddin Kudratov

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

Sen gerekecek pip install pandasilk
Boris

1

Bir panda veri çerçevesini indeksleme ve alt kümeleme yönteminiz sayesinde, bir csv dosyasından tek bir sütunu bir değişkene çıkarmanın çok kolay bir yolu:

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

Dikkate alınması gereken birkaç nokta:

Yukarıdaki pasaj bir panda üretecek Seriesve üretmeyecektir dataframe. usecolsHız bir sorun ise ayhan'ın önerisi de daha hızlı olacaktır. %timeit2122 KB büyüklüğünde bir csv dosyası kullanılarak iki farklı yaklaşımın test edilmesi 22.8 ms, kullanım yaklaşımları yaklaşımı ve 53 msbenim önerdiğim yaklaşım için ortaya çıkar.

Ve unutma import pandas as pd


0

Sütunları ayrı ayrı işlemeniz gerekiyorsa, sütunları zip(*iterable)desenli olarak yapılandırmayı seviyorum (etkin bir şekilde "sıkıştırmayı aç"). Yani örneğiniz için:

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

-1

Almak için sütun adı kullanmak yerine, readlines () daha iyi bir kullanımı taleb () önlemek döngü ve tam dosya okuma ve dizi içinde depolanması.

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

    # get number of columns

    line = csvfile.readline()

    first_item = line.split(',')
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.