làm thế nào để bạn lọc khung dữ liệu gấu trúc theo nhiều cột


98

Để lọc khung dữ liệu (df) theo một cột, nếu chúng tôi xem xét dữ liệu với nam và nữ, chúng ta có thể:

males = df[df[Gender]=='Male']

Câu hỏi 1 - Nhưng điều gì sẽ xảy ra nếu dữ liệu kéo dài nhiều năm và tôi muốn chỉ nhìn thấy nam giới trong năm 2014?

Trong các ngôn ngữ khác, tôi có thể làm điều gì đó như:

if A = "Male" and if B = "2014" then 

(ngoại trừ tôi muốn làm điều này và lấy một tập hợp con của khung dữ liệu ban đầu trong một đối tượng khung dữ liệu mới)

Câu hỏi 2. Làm cách nào để thực hiện việc này trong vòng lặp và tạo đối tượng khung dữ liệu cho từng nhóm năm và giới tính duy nhất (ví dụ: df cho: 2013-Male, 2013-Female, 2014-Male và 2014-Female

for y in year:

for g in gender:

df = .....

Bạn muốn lọc nó hay nhóm nó? Nếu bạn muốn tạo DataFrame riêng biệt cho từng nhóm năm và giới tính duy nhất, hãy xem groupby.
BrenBarn

1
Câu trả lời này cung cấp một cái nhìn tổng quan toàn diện về lập chỉ mục boolean và các toán tử logic trong gấu trúc.
cs95

Câu trả lời:


168

Sử dụng &toán tử, đừng quên bọc các câu lệnh con bằng ():

males = df[(df[Gender]=='Male') & (df[Year]==2014)]

Để lưu trữ các khung dữ liệu của bạn trong một dictvòng lặp sử dụng vòng lặp for:

from collections import defaultdict
dic={}
for g in ['male', 'female']:
  dic[g]=defaultdict(dict)
  for y in [2013, 2014]:
    dic[g][y]=df[(df[Gender]==g) & (df[Year]==y)] #store the DataFrames to a dict of dict

BIÊN TẬP:

Bản demo cho getDF:

def getDF(dic, gender, year):
  return dic[gender][year]

print genDF(dic, 'male', 2014)

câu trả lời tuyệt vời zhangxaochen - bạn có thể chỉnh sửa câu trả lời của mình để hiển thị ở dưới cùng cách bạn có thể thực hiện vòng lặp for, tạo khung dữ liệu (với dữ liệu năm và giới tính) nhưng thêm chúng vào từ điển để chúng có thể được truy cập sau này bằng phương pháp getDF của tôi không? def GetDF (dict, key): return dict [key]
yoshiserry

@yoshiserry của keybạn getDFnhư thế nào? một tham số duy nhất hay một bộ khóa? hãy cụ thể làm ơn;)
zhangxaochen

xin chào, đó là một phím duy nhất, chỉ là một từ, sẽ tương ứng với giới tính (nam hoặc nữ) hoặc năm (13, 14). Không biết là bạn có thể có nhiều phím. Bạn có thể chia sẻ một ví dụ về thời gian và cách bạn làm điều này?
yoshiserry

bạn cũng có thể xem câu hỏi này. Tôi cảm thấy như bạn có thể trả lời nó. Lại liên quan đến khung dữ liệu gấu trúc. stackoverflow.com/questions/22086619/…
yoshiserry

1
Lưu ý rằng cả GenderYearphải là chuỗi, tức là 'Gender''Year'.
Steven C. Howell

22

Đối với các hàm boolean tổng quát hơn mà bạn muốn sử dụng làm bộ lọc và phụ thuộc vào nhiều cột, bạn có thể sử dụng:

df = df[df[['col_1','col_2']].apply(lambda x: f(*x), axis=1)]

trong đó f là một hàm được áp dụng cho mọi cặp phần tử (x1, x2) từ col_1 và col_2 và trả về True hoặc False tùy thuộc vào bất kỳ điều kiện nào bạn muốn (x1, x2).


11

Bắt đầu từ gấu trúc 0,13 , đây là cách hiệu quả nhất.

df.query('Gender=="Male" & Year=="2014" ')

1
Tại sao điều này phải hiệu quả hơn câu trả lời được chấp nhận?
Bouncner

@Bouncner chỉ cần xác minh nó với câu trả lời được bình chọn cao.
redreamality

4
Câu trả lời này có thể được cải thiện bằng cách hiển thị điểm chuẩn
nardeas

6

Trong trường hợp ai đó thắc mắc đâu là cách lọc nhanh hơn (câu trả lời được chấp nhận hoặc câu trả lời từ @redreamality):

import pandas as pd
import numpy as np

length = 100_000
df = pd.DataFrame()
df['Year'] = np.random.randint(1950, 2019, size=length)
df['Gender'] = np.random.choice(['Male', 'Female'], length)

%timeit df.query('Gender=="Male" & Year=="2014" ')
%timeit df[(df['Gender']=='Male') & (df['Year']==2014)]

Kết quả cho 100.000 hàng:

6.67 ms ± 557 µs per loop (mean ± std. dev. of 7 runs, 100 loops each)
5.54 ms ± 536 µs per loop (mean ± std. dev. of 7 runs, 100 loops each)

Kết quả cho 10.000.000 hàng:

326 ms ± 6.52 ms per loop (mean ± std. dev. of 7 runs, 1 loop each)
472 ms ± 25.1 ms per loop (mean ± std. dev. of 7 runs, 1 loop each)

Vì vậy, kết quả phụ thuộc vào kích thước và dữ liệu. Trên máy tính xách tay của tôi, query()nhanh hơn sau 500 nghìn hàng. Hơn nữa, tìm kiếm chuỗi trong Year=="2014"có chi phí không cần thiết ( Year==2014nhanh hơn).


1

Bạn có thể tạo chức năng lọc của riêng mình bằng cách sử dụng querytrong pandas. Ở đây bạn có lọc dfkết quả theo tất cả các kwargstham số. Đừng quên thêm một số trình xác nhận ( kwargslọc) để có được chức năng lọc cho riêng bạn df.

def filter(df, **kwargs):
    query_list = []
    for key in kwargs.keys():
        query_list.append(f'{key}=="{kwargs[key]}"')
    query = ' & '.join(query_list)
    return df.query(query)

Cảm ơn vì giải pháp thanh lịch! Tôi nghĩ nó là tốt nhất trong số tất cả những thứ còn lại. Nó kết hợp hiệu quả của việc sử dụng truy vấn với tính linh hoạt của việc sử dụng nó như một hàm.
A Merii

0

Bạn có thể lọc theo nhiều cột (nhiều hơn hai) bằng cách sử dụng np.logical_andtoán tử để thay thế &(hoặc np.logical_orđể thay thế |)

Đây là một ví dụ về hàm thực hiện công việc, nếu bạn cung cấp các giá trị đích cho nhiều trường. Bạn có thể điều chỉnh nó cho các loại lọc khác nhau và không:

def filter_df(df, filter_values):
    """Filter df by matching targets for multiple columns.

    Args:
        df (pd.DataFrame): dataframe
        filter_values (None or dict): Dictionary of the form:
                `{<field>: <target_values_list>}`
            used to filter columns data.
    """
    import numpy as np
    if filter_values is None or not filter_values:
        return df
    return df[
        np.logical_and.reduce([
            df[column].isin(target_values) 
            for column, target_values in filter_values.items()
        ])
    ]

Sử dụng:

df = pd.DataFrame({'a': [1, 2, 3, 4], 'b': [1, 2, 3, 4]})

filter_df(df, {
    'a': [1, 2, 3],
    'b': [1, 2, 4]
})
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.