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

98

У меня есть файл 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: исправлено неправильное использование заголовка.

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

Ответы:

115

Ответ @chip полностью упускает из виду два аргумента ключевого слова.

  • имена необходимы только тогда, когда нет заголовка и вы хотите указать другие аргументы, используя имена столбцов, а не целочисленные индексы.
  • Предполагается, что usecols предоставляет фильтр перед чтением всего 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),
        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
Мак
источник
1
Это учебное решение для анализа данных CSV, но в то время я намеревался использовать аргумент имен, потому что у реальных данных не было заголовка.
чип
2
В таком случае вы не указываете header=0. Вы хотите использовать, header=Noneа затем использовать namesдополнительно.
Mack
Но по-прежнему использовать usecolsс целочисленными индексами для столбцов, которые нужно сохранить @Mack?
Mr_and_Mrs_D 03
22

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

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

а) вы указываете 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
Теодрос Зеллеке
источник
1
Спасибо. Я так и не придумал правильную комбинацию перестановки namesчисел и на основе usecolsправильных данных.
чип
8

Если ваш 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
чип
источник
почему index_col создает проблему в моем случае, я попытался использовать имя столбца, как вы предложили, но это сработало, если я передал номер столбца.
YouAreAwesome
5
однако это пустая трата ресурсов
Mr_and_Mrs_D 03
1

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

df1 = pd.read_csv('foo.csv',
     header=0,
     index_col=False,
     names=["dummy", "date", "loc", "x"], 
     index_col=["date", "loc"], 
     usecols=["dummy", "date", "loc", "x"],
     parse_dates=["date"])
  print df1
Auday Berro
источник
-4

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

Мохан
источник
2
Это может быть проще, но при этом значительно медленнее. Когда вы работаете с большими наборами данных (в настоящее время я сам работаю с одним файлом CSV размером 13 ГБ), гораздо важнее не ждать часами загрузки файла.
Fake Name