2013-05-12 42 views
107

Tôi đang cố gắng phân tích cú pháp thông qua tệp csv và trích xuất dữ liệu từ các cột cụ thể.Đọc các cột cụ thể từ tệp csv với mô-đun csv?

Ví dụ csv:

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

Tôi đang cố gắng để nắm bắt các cột chỉ cụ thể, nói ID, Name, ZipPhone.

Mã Tôi đã nhìn vào đã khiến tôi tin tôi có thể gọi các cột cụ thể bằng số tương ứng của nó, vì vậy tức là: Name sẽ tương ứng với 2 và lặp lại qua mỗi hàng sử dụng row[2] sẽ tạo ra tất cả các mục trong cột 2. Chỉ có nó không.

Dưới đây là những gì tôi đã làm như vậy cho đến nay:

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 

và tôi hy vọng rằng điều này sẽ in ra chỉ có các cột cụ thể tôi muốn cho mỗi hàng, ngoại trừ nó không, tôi nhận được cột cuối cùng chỉ có.

+0

tại sao ''rb'' gắn cờ thành' open() '? không nên đơn giản là 'r'? – Elazar

+6

@Elazar: trong Python 2 (mà OP đang sử dụng) '" rb "' là thích hợp để chuyển tới 'csv.reader'. – DSM

+0

Tại sao tệp CSV mẫu của bạn hiển thị ký tự đường ống làm dấu phân cách nhưng mã mẫu của bạn sử dụng khoảng trắng? –

Trả lời

114

Cách duy nhất bạn sẽ nhận được cột cuối cùng từ mã này là nếu bạn không bao gồm tuyên bố in của bạn trongfor vòng lặp của bạn.

này rất có thể vào cuối mã của bạn:

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

Bạn muốn nó được này:

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

Bây giờ chúng ta đã đề cập sai lầm của bạn, tôi muốn dành thời gian này để giới thiệu bạn với mô-đun pandas.

Pandas là ngoạn mục để đối phó với các tập tin csv, và đoạn mã sau sẽ là tất cả các bạn cần phải đọc một csv và lưu toàn bộ một cột vào một biến:

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

vì vậy nếu bạn muốn lưu tất cả các thông tin trong cột của bạn Names vào một biến, đây là tất cả các bạn cần làm:

names = df.Names 

đó là một mô-đun tuyệt vời và tôi đề nghị bạn nhìn vào nó. Nếu vì lý do nào đó, bản in của bạn nằm trong vòng lặp for và nó vẫn chỉ in ra cột cuối cùng, điều này không nên xảy ra, nhưng hãy cho tôi biết nếu giả định của tôi sai.Mã đã đăng của bạn có nhiều lỗi thụt đầu dòng nên rất khó để biết những gì được cho là ở đâu. Hy vọng điều này hữu ích!

+1

Có thể xóa số chỉ mục khỏi truy vấn không? @Ryan Saxe –

+0

Có, chỉ cần lặp qua nó trong vòng lặp for. –

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

Với một tập tin như sản lượng

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

Will

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

Hoặc cách khác nếu bạn muốn đánh chỉ số cho các cột:

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

Để thay đổi deliminator add delimiter=" " để instantiation thích hợp, tức là reader = csv.reader(f,delimiter=" ")

+0

Công việc tuyệt vời @HennyH. –

11

Bạn có thể sử dụng numpy.loadtext(filename). Ví dụ, nếu đây là cơ sở dữ liệu của bạn .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 | 

Và bạn muốn Name cột:

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

dễ dàng hơn bạn có thể sử dụng genfromtext:

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

@G Có phải là một r bên cạnh 'filepath \ name.csv'? – 114

+0

@ 114 vâng, đó là cách tốt nhất để tránh lỗi .... –

2

Bối cảnh: Đối với loại làm việc bạn nên sử dụng thư viện python python tuyệt vời. Điều đó sẽ giúp bạn tiết kiệm rất nhiều công sức và thất vọng tiềm năng khi thực hiện những việc 'thủ công' bằng mô-đun csv chuẩn. AFAIK, những người duy nhất vẫn sử dụng mô-đun csv là những người chưa phát hiện ra các công cụ tốt hơn để làm việc với dữ liệu dạng bảng (gấu trúc, petl, v.v.), điều đó là tốt, nhưng nếu bạn có kế hoạch làm việc với nhiều dữ liệu sự nghiệp của bạn từ nhiều nguồn khác lạ, học một cái gì đó như petl là một trong những đầu tư tốt nhất bạn có thể thực hiện. Để bắt đầu chỉ mất 30 phút sau khi bạn đã cài đặt pip petl. Tài liệu là tuyệt vời.

Trả lời: Giả sử bạn có bảng đầu tiên trong tệp csv (bạn cũng có thể tải trực tiếp từ cơ sở dữ liệu bằng petl). Sau đó, bạn chỉ cần tải nó và làm như sau.

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

Với pandas bạn có thể sử dụng read_csv với usecols tham số:

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

Ví dụ:

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 
0

Để lấy tên cột, thay vì sử dụng readlines() sử dụng tốt hơn readli ne() để tránh vòng lặp & đọc toàn bộ tệp & lưu trữ tệp trong mảng.

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

    # get number of columns 

    line = csvfile.readline() 

    first_item = line.split(',') 
3

Sử dụng pandas:

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

Một chút giải pháp bộ nhớ thân thiện hơn, nếu bạn thực sự cần những byte (ném đi các cột không cần thiết vào thời điểm phân tích cú pháp):

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

T.B. Tôi chỉ tập hợp những gì người khác đã nói một cách đơn giản. Câu trả lời thực tế được lấy từ herehere.

+0

Tôi nghĩ Pandas là một giải pháp hoàn toàn có thể chấp nhận được. Tôi sử dụng Pandas thường xuyên và thực sự thích thư viện, nhưng câu hỏi này đã đề cập cụ thể đến mô-đun CSV. – frankV

+0

@frankV Vâng, tiêu đề, các thẻ và đoạn đầu tiên không cấm gấu trúc theo bất kỳ cách nào, AFAI có thể xem. Tôi đã thực sự chỉ hy vọng thêm một câu trả lời đơn giản hơn cho những người đã thực hiện ở đây (câu trả lời khác sử dụng gấu trúc, quá). – VasyaNovikov