Чтение определенных столбцов из файла CSV с модулем CSV?


176

Я пытаюсь разобрать файл CSV и извлечь данные только из определенных столбцов.

Пример CSV:

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

Я пытаюсь захватить только определенные столбцы, скажем ID, Name, Zipи Phone.

Код, на который я посмотрел, заставил меня поверить, что я могу вызвать конкретный столбец по соответствующему номеру, то есть: Nameбудет соответствовать, 2и итерация по каждой строке с использованием row[2]приведет к созданию всех элементов в столбце 2. Только это не так.

Вот что я сделал до сих пор:

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

и я ожидаю, что при этом будут напечатаны только те столбцы, которые мне нужны для каждой строки, кроме случаев, когда я получаю только последний столбец.


1
зачем 'rb'флаг open()? не должно ли быть просто r?
Elazar

7
@Elazar: в Python 2 (который использует OP) "rb"подходит для перехода на csv.reader.
DSM

Почему в вашем примере CSV-файла в качестве разделителя указывается символ канала, а в примере кода используется пробел?
Келли С. Френч

1
@ KellyS.French Я думал, что это поможет визуализировать данные для целей этого вопроса.
frankV

Ответы:


187

Единственный способ получить последний столбец из этого кода - это если вы не включите оператор print в свой forцикл.

Это, скорее всего, конец вашего кода:

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

Вы хотите, чтобы это было так:

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

Теперь, когда мы рассмотрели вашу ошибку, я хотел бы воспользоваться этим временем, чтобы познакомить вас с модулем панд .

Pandas отлично подходит для работы с CSV-файлами, и следующий код будет всем, что вам нужно, чтобы прочитать CSV-файл и сохранить весь столбец в переменную:

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

поэтому, если вы хотите сохранить всю информацию в столбце Namesв переменную, это все, что вам нужно сделать:

names = df.Names

Это отличный модуль, и я предлагаю вам изучить его. Если по какой-то причине ваше заявление на печать было в forцикле, и оно все еще только печатало последний столбец, чего не должно быть, но дайте мне знать, если мое предположение было неверным. В вашем опубликованном коде много ошибок отступов, поэтому было трудно понять, что и где должно было быть. Надеюсь, это было полезно!


1
Можно ли удалить индексные номера из запроса? @ Райан Сакс
Малахи Базар

Да, просто переберите его в цикле for.
Давид галант

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

С файлом вроде

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

Будет выходной

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

Или в качестве альтернативы, если вы хотите числовую индексацию для столбцов:

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

Для изменения разделителя добавьте delimiter=" "соответствующий экземпляр, т.е.reader = csv.reader(f,delimiter=" ")


30

Используйте панд :

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

Откажитесь от ненужных столбцов во время разбора:

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

PS Я просто обобщаю то, что сказали другие, в простой форме. Актуальные ответы принимаются здесь и здесь .


1
Я думаю, что Панды - это вполне приемлемое решение. Я часто использую Pandas и очень люблю библиотеку, но этот вопрос специально касался модуля CSV.
frankV

1
@frankV Ну, в AFAI видно, что заголовок, теги и первый абзац не запрещают пандам. На самом деле я просто надеялся добавить более простой ответ к уже сделанным здесь (другие ответы тоже используют панд).
Василий Новиков

18

С пандами вы можете использовать read_csvс usecolsпараметром:

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

Пример:

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

Вы можете использовать numpy.loadtext(filename). Например, если это ваша база данных .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 |

И вы хотите Nameстолбец:

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

Более легко вы можете использовать genfromtext:

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

@G Должен ли быть r рядом с 'filepath \ name.csv'?
114

6

Контекст: Для этого типа работы вы должны использовать удивительную библиотеку Python Petl. Это избавит вас от большой работы и потенциального разочарования от выполнения действий «вручную» со стандартным модулем CSV. AFAIK, единственные люди, которые все еще используют модуль csv, - это те, кто еще не обнаружил лучших инструментов для работы с табличными данными (pandas, petl и т. Д.), Что хорошо, но если вы планируете работать с большим количеством данных в Ваша карьера из разных странных источников, изучение чего-то вроде petl - одна из лучших инвестиций, которую вы можете сделать. Чтобы начать, нужно только через 30 минут после того, как вы сделали pip install petl. Документация отличная.

Ответ: Допустим, у вас есть первая таблица в CSV-файле (вы также можете загрузить напрямую из базы данных, используя petl). Тогда вы просто загрузите его и сделаете следующее.

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

Я думаю, что есть более простой способ

import pandas as pd

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

Так вот iloc[:, 0], :значит , все значения, 0означает положение колонны. в примере ниже IDбудет выбран

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

Если это сработает, ребята, пожалуйста, проголосуйте, сообщите об этом другим :)
Нуриддин Кудратов

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

Вам придется pip install pandasсначала
Борис

1

Благодаря тому, что вы можете индексировать и размещать подгруппу данных pandas, очень простой способ извлечь один столбец из файла csv в переменную:

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

Несколько вещей для рассмотрения:

Фрагмент выше будет производить панды, Seriesа не dataframe. Предложение от айхана с usecolsтакже будет быстрее, если скорость является проблемой. Тестирование двух разных подходов с использованием %timeitcsv-файла размером 2122 КБ приводит 22.8 msк подходу usecols и 53 msк моему предложенному подходу.

И не забывай import pandas as pd


0

Если вам нужно обрабатывать столбцы по отдельности, мне нравится деструктурировать столбцы с помощью zip(*iterable)шаблона (эффективно «разархивировать»). Итак, для вашего примера:

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

-1

Получить имя столбца вместо использования readlines () лучше использовать readline (), чтобы избежать зацикливания, чтения всего файла и сохранения его в массиве.

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

    # get number of columns

    line = csvfile.readline()

    first_item = line.split(',')
Используя наш сайт, вы подтверждаете, что прочитали и поняли нашу Политику в отношении файлов cookie и Политику конфиденциальности.
Licensed under cc by-sa 3.0 with attribution required.