pandas read_csv и фильтровать столбцы с помощью usecols

У меня есть файл csv, который неправильно отображается с pandas.read_csv, когда я фильтрую столбцы с помощью usecols и использую несколько индексов.

import pandas as pd
csv = r"""dummy,date,loc,x
   bar,20090101,a,1
   bar,20090102,a,3
   bar,20090103,a,5
   bar,20090101,b,1
   bar,20090102,b,3
   bar,20090103,b,5"""

f = open('foo.csv', 'w')
f.write(csv)
f.close()

df1 = pd.read_csv('foo.csv',
        header=0,
        names=["dummy", "date", "loc", "x"], 
        index_col=["date", "loc"], 
        usecols=["dummy", "date", "loc", "x"],
        parse_dates=["date"])
print df1

# Ignore the dummy columns
df2 = pd.read_csv('foo.csv', 
        index_col=["date", "loc"], 
        usecols=["date", "loc", "x"], # <----------- Changed
        parse_dates=["date"],
        header=0,
        names=["dummy", "date", "loc", "x"])
print df2

Я ожидаю, что df1 и df2 должны быть одинаковыми, за исключением отсутствующего фиктивного столбца, но столбцы имеют неправильную маркировку. Также дата анализируется как дата.

In [118]: %run test.py
               dummy  x
date       loc
2009-01-01 a     bar  1
2009-01-02 a     bar  3
2009-01-03 a     bar  5
2009-01-01 b     bar  1
2009-01-02 b     bar  3
2009-01-03 b     bar  5
              date
date loc
a    1    20090101
     3    20090102
     5    20090103
b    1    20090101
     3    20090102
     5    20090103

Использование номеров столбцов вместо имен вызывает у меня ту же проблему. Я могу обойти проблему, отбросив фиктивный столбец после шага read_csv, но я пытаюсь понять, что происходит не так. Я использую панды 0.10.1.

edit: исправлено неправильное использование заголовка.


person chip    schedule 22.02.2013    source источник
comment
Что-то еще, ваше использование ключевых слов header и names неверно (поэтому в вашем примере отсутствует первая строка. header ожидает int (по умолчанию 0) в качестве строки с заголовком. Потому что вы даете 'True', которое интерпретируется как 1, вторая строка (первая строка данных) используется в качестве заголовка и отсутствует. Однако имена столбцов верны, потому что вы перезаписываете их аргументом names. Но вы можете оставить их, и первая строка используется для столбца имена по умолчанию, однако это не решает ваш первоначальный вопрос.   -  person joris    schedule 22.02.2013
comment
Это похоже на usecols ошибку. Возможно, связано с ошибкой 2654?   -  person abudis    schedule 22.02.2013
comment
ошибка все еще существует без имен и аргументов заголовка, хорошая находка.   -  person Andy Hayden    schedule 22.02.2013
comment
@andy Я ткну его еще немного и отправлю в pandas bugs. Я ценю проверку на вменяемость.   -  person chip    schedule 22.02.2013


Ответы (5)


Решение заключается в понимании этих двух аргументов ключевого слова:

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

Так как у вас есть строка заголовка, достаточно передать header=0, а дополнительная передача names может сбивать с толку pd.read_csv.

Удаление names из второго вызова дает желаемый результат:

import pandas as pd
from StringIO import StringIO

csv = r"""dummy,date,loc,x
bar,20090101,a,1
bar,20090102,a,3
bar,20090103,a,5
bar,20090101,b,1
bar,20090102,b,3
bar,20090103,b,5"""

df = pd.read_csv(StringIO(csv),
        header=0,
        index_col=["date", "loc"], 
        usecols=["date", "loc", "x"],
        parse_dates=["date"])

Что дает нам:

                x
date       loc
2009-01-01 a    1
2009-01-02 a    3
2009-01-03 a    5
2009-01-01 b    1
2009-01-02 b    3
2009-01-03 b    5
person Mack    schedule 06.01.2015
comment
Это учебное решение для анализа данных CSV, но в то время я намеревался использовать аргумент names, потому что у реальных данных не было заголовка. - person chip; 06.01.2015
comment
В этом случае вы не указываете header=0. Вы можете использовать header=None, а затем дополнительно использовать names. - person Mack; 06.01.2015
comment
Но все же использовать usecols с целочисленными индексами для столбцов, которые нужно сохранить @Mack? - person Mr_and_Mrs_D; 03.12.2018
comment
@Mr_and_Mrs_D в случае, который мы обсуждаем, вам нужно будет использовать только целочисленные индексы, если вы не передадите names. Вы можете использовать индексы в usecols в любом случае, но если вы все равно собираетесь передать names (что вам все равно нужно сделать, если вы хотите указать parse_dates и index_col, используя эти имена), вы также можете использовать имена в usecols , поскольку у вас меньше шансов ошибиться. - person Mack; 04.01.2021

Этот код выполняет то, что вы хотите, - также это странно и, безусловно, содержит ошибки:

Я заметил, что это работает, когда:

а) указываете index_col отн. к количеству столбцов, которые вы действительно используете - поэтому в этом примере это три столбца, а не четыре (вы отбрасываете dummy и начинаете отсчет с этого момента)

б) то же для parse_dates

в) не так для usecols;) по понятным причинам

г) здесь я адаптировал names, чтобы отразить это поведение

import pandas as pd
from StringIO import StringIO

csv = """dummy,date,loc,x
bar,20090101,a,1
bar,20090102,a,3
bar,20090103,a,5
bar,20090101,b,1
bar,20090102,b,3
bar,20090103,b,5
"""

df = pd.read_csv(StringIO(csv),
        index_col=[0,1],
        usecols=[1,2,3], 
        parse_dates=[0],
        header=0,
        names=["date", "loc", "", "x"])

print df

который печатает

                x
date       loc   
2009-01-01 a    1
2009-01-02 a    3
2009-01-03 a    5
2009-01-01 b    1
2009-01-02 b    3
2009-01-03 b    5
person Theodros Zelleke    schedule 22.02.2013
comment
Спасибо. Я так и не придумал правильную комбинацию перестановки names и чисел на основе usecols, чтобы данные пришли правильно. - person chip; 23.02.2013

Если ваш CSV-файл содержит дополнительные данные, столбцы можно удалить из DataFrame после импорта.

import pandas as pd
from StringIO import StringIO

csv = r"""dummy,date,loc,x
bar,20090101,a,1
bar,20090102,a,3
bar,20090103,a,5
bar,20090101,b,1
bar,20090102,b,3
bar,20090103,b,5"""

df = pd.read_csv(StringIO(csv),
        index_col=["date", "loc"], 
        usecols=["dummy", "date", "loc", "x"],
        parse_dates=["date"],
        header=0,
        names=["dummy", "date", "loc", "x"])
del df['dummy']

Что дает нам:

                x
date       loc
2009-01-01 a    1
2009-01-02 a    3
2009-01-03 a    5
2009-01-01 b    1
2009-01-02 b    3
2009-01-03 b    5
person chip    schedule 26.02.2013
comment
почему index_col создает проблему в моем случае, я попытался использовать имя столбца, как вы предложили, но это сработало, если я передал номер столбца. - person Indrajeet Gour; 07.04.2018
comment
однако это пустая трата ресурсов - person Mr_and_Mrs_D; 03.12.2018

Вам нужно просто добавить параметр index_col=False

df1 = pd.read_csv('foo.csv',
     header=0,
     index_col=False,
     names=["dummy", "date", "loc", "x"], 
     usecols=["dummy", "date", "loc", "x"],
     parse_dates=["date"])
  print df1
person Auday Berro    schedule 12.08.2019

сначала импортируйте csv и используйте csv.DictReader, его легко обработать ...

person Mohan    schedule 25.02.2013
comment
Это может быть проще, но также значительно медленнее. Когда вы работаете с большими наборами данных (в настоящее время я сам работаю с одним файлом CSV размером 13 ГБ), гораздо важнее не ждать часами загрузки файла. - person Fake Name; 18.12.2013