Читати конкретні стовпці з файлу 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?
Елазар

7
@Elazar: в Python 2 (який використовує ОП) "rb"підходить для переходу csv.reader.
DSM

Чому у вашому прикладі CSV-файл відображається символ труби як роздільник, але у вашому прикладі коду використовується пробіл?
Келлі С. Французька

1
@ KellyS.French Я думав, що це допоможе візуалізувати дані для цілей цього питання.
франкV

Відповіді:


187

Єдиний спосіб отримати останній стовпець з цього коду - це якщо ви не включите у свій 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
Чи можливо видалити індексні числа із запиту? @Ryan Saxe
Малахій Базар

Так, просто повторіть його в циклі 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'])

З файлом на кшталт

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.
франкV

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 Чи має бути поруч "filepath \ name.csv"?
114

6

Контекст: Для цього виду роботи слід використовувати дивовижну бібліотеку python petl. Це допоможе вам заощадити багато роботи та потенційних розладів від того, щоб робити справи "вручну" зі стандартним модулем csv. AFAIK, єдиними людьми, які все ще використовують модуль csv, є ті, хто ще не виявив кращих інструментів для роботи з табличними даними (панди, petl тощо), що добре, але якщо ви плануєте працювати з великою кількістю даних у Ваша кар'єра з різних дивних джерел, вивчення чогось подібного до Petl - одна з найкращих інвестицій, яку Ви можете зробити. Для початку слід зайняти лише 30 хвилин після того, як ви закінчили встановити файл 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

Завдяки тому, як ви можете індексувати та підмножити кадр даних панди, дуже простим способом вилучення одного стовпця з файлу 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.