pandas read_csv và lọc các cột bằng usecols


97

Tôi có một tệp csv không đến chính xác pandas.read_csvkhi tôi lọc các cột usecolsvà sử dụng nhiều chỉ mục.

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

Tôi hy vọng rằng df1 và df2 phải giống nhau ngoại trừ cột giả bị thiếu, nhưng các cột bị gắn nhãn sai. Ngoài ra ngày được phân tích cú pháp như một ngày.

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

Sử dụng số cột thay vì tên cho tôi cùng một vấn đề. Tôi có thể giải quyết vấn đề này bằng cách bỏ cột giả sau bước read_csv, nhưng tôi đang cố gắng hiểu điều gì đang xảy ra. Tôi đang sử dụng gấu trúc 0.10.1.

chỉnh sửa: đã sửa lỗi sử dụng tiêu đề không hợp lệ.


1
Một cái gì đó khác, cách sử dụng headernamestừ khóa của bạn không đúng (đó là lý do tại sao hàng đầu tiên bị thiếu trong ví dụ của bạn. Bạn headermong đợi giá trị int (mặc định là 0) là hàng có tiêu đề. Bởi vì bạn cung cấp 'True' được hiểu là 1, hàng thứ hai (hàng dữ liệu đầu tiên) được sử dụng làm tiêu đề và bị thiếu. Tuy nhiên, tên cột chính xác vì bạn ghi đè lên nó bằng namesđối số. Nhưng bạn có thể để lại cả hai và hàng đầu tiên được sử dụng cho tên cột theo mặc định. Tuy nhiên, nó không giải quyết được câu hỏi ban đầu của bạn.
joris

1
Điều này trông giống như một usecolslỗi. Có thể liên quan đến lỗi 2654 ?
abudis

lỗi vẫn ở đó mà không có tên và đối số tiêu đề, tìm tốt.
Andy Hayden

@andy Tôi sẽ chọc vào nó một chút nữa và nộp nó cho lũ gấu trúc. Tôi đánh giá cao việc kiểm tra sự tỉnh táo.
chip

Câu trả lời:


113

Câu trả lời của @chip hoàn toàn thiếu điểm của hai đối số từ khóa.

  • tên chỉ cần thiết khi không có tiêu đề và bạn muốn chỉ định các đối số khác bằng cách sử dụng tên cột thay vì chỉ số nguyên.
  • usecols được cho là cung cấp một bộ lọc trước khi đọc toàn bộ DataFrame vào bộ nhớ; nếu được sử dụng đúng cách, không bao giờ phải xóa cột sau khi đọc.

Giải pháp này khắc phục những điều kỳ quặc đó:

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

Điều này mang lại cho chúng tôi:

                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
Đây là giải pháp sách giáo khoa để phân tích cú pháp dữ liệu CSV, nhưng tại thời điểm đó, tôi có ý định sử dụng đối số tên vì dữ liệu thực không có tiêu đề.
chip

2
Trong trường hợp đó, bạn sẽ không chỉ định header=0. Bạn muốn sử dụng header=Nonevà sau đó sử dụng namesthêm vào.
Mack

Nhưng vẫn sử dụng usecolsvới các chỉ mục số nguyên cho các cột mà bạn muốn giữ lại @Mack?
Mr_and_Mrs_D

22

Mã này đạt được những gì bạn muốn --- cũng có lỗi kỳ lạ và chắc chắn của nó:

Tôi quan sát thấy rằng nó hoạt động khi:

a) bạn chỉ định index_colrel. đến số cột bạn thực sự sử dụng - vì vậy ba cột của nó trong ví dụ này, không phải bốn (bạn thả xuống dummyvà bắt đầu đếm từ đó trở đi)

b) tương tự cho parse_dates

c) không phải như vậy vì usecols;) vì những lý do rõ ràng

d) ở đây tôi đã điều chỉnh namesđể phản ánh hành vi này

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

cái nào in

                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
Cảm ơn. Tôi chưa bao giờ tìm ra sự kết hợp đúng đắn giữa việc sắp xếp lại các namessố và các số dựa trên usecolsđể dữ liệu trở nên chính xác.
chip

8

Nếu tệp csv của bạn chứa thêm dữ liệu, các cột có thể bị xóa khỏi DataFrame sau khi nhập.

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

Điều này mang lại cho chúng tôi:

                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

tại sao index_col lại tạo ra vấn đề trong trường hợp của tôi, tôi đã cố gắng sử dụng tên cột như bạn đã đề xuất, nhưng nó hoạt động hiệu quả nếu tôi chuyển số cột.
YouAreAwesome

4
Tuy nhiên, điều này thật lãng phí tài nguyên
Mr_and_Mrs_D

0

Bạn chỉ cần thêm index_col=Falsetham số

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

-4

nhập csv trước và sử dụng csv.DictReader dễ xử lý ...


2
Điều này có thể dễ dàng hơn, nhưng cũng chậm hơn rất nhiều. Khi bạn đang làm việc trên các tập dữ liệu lớn (tôi hiện đang tự làm việc với một tệp CSV 13 GB), việc không phải đợi hàng giờ để tải tệp trở nên quan trọng hơn nhiều.
Tên giả mạo
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.