2012-01-18 45 views
29

Tôi có một khung dữ liệu df trong gấu trúc được xây dựng bằng cách sử dụng pandas.read_table từ tệp csv. Các khung dữ liệu có một số cột và nó được lập chỉ mục bởi một trong các cột (là duy nhất, trong đó mỗi hàng có một giá trị duy nhất cho cột đó được sử dụng để lập chỉ mục.)chọn qua nhiều cột với gấu trúc python?

Làm cách nào tôi có thể chọn các hàng của khung dữ liệu dựa trên bộ lọc "phức tạp" được áp dụng cho nhiều cột? Tôi có thể dễ dàng chọn ra các lát của dataframe nơi cột colA lớn hơn 10 ví dụ:

df_greater_than10 = df[df["colA"] > 10] 

Nhưng nếu tôi muốn có một bộ lọc như: chọn lát df nơi bất kỳ của cột lớn hơn hơn 10?

Hoặc nơi giá trị cho colA lớn hơn 10 nhưng giá trị cho colB nhỏ hơn 5?

Chúng được triển khai như thế nào trong gấu trúc? Cảm ơn.

Trả lời

36

Tôi khuyến khích bạn đặt những câu hỏi này trên mailing list, nhưng trong mọi trường hợp, nó vẫn là một vấn đề cấp thấp rất nhiều khi làm việc với các mảng NumPy bên dưới. Ví dụ, để chọn hàng nơi các giá trị trong cột bất kỳ quá, nói, 1,5 trong ví dụ này:

In [11]: df 
Out[11]: 
      A  B  C  D  
2000-01-03 -0.59885 -0.18141 -0.68828 -0.77572 
2000-01-04 0.83935 0.15993 0.95911 -1.12959 
2000-01-05 2.80215 -0.10858 -1.62114 -0.20170 
2000-01-06 0.71670 -0.26707 1.36029 1.74254 
2000-01-07 -0.45749 0.22750 0.46291 -0.58431 
2000-01-10 -0.78702 0.44006 -0.36881 -0.13884 
2000-01-11 0.79577 -0.09198 0.14119 0.02668 
2000-01-12 -0.32297 0.62332 1.93595 0.78024 
2000-01-13 1.74683 -1.57738 -0.02134 0.11596 
2000-01-14 -0.55613 0.92145 -0.22832 1.56631 
2000-01-17 -0.55233 -0.28859 -1.18190 -0.80723 
2000-01-18 0.73274 0.24387 0.88146 -0.94490 
2000-01-19 0.56644 -0.49321 1.17584 -0.17585 
2000-01-20 1.56441 0.62331 -0.26904 0.11952 
2000-01-21 0.61834 0.17463 -1.62439 0.99103 
2000-01-24 0.86378 -0.68111 -0.15788 -0.16670 
2000-01-25 -1.12230 -0.16128 1.20401 1.08945 
2000-01-26 -0.63115 0.76077 -0.92795 -2.17118 
2000-01-27 1.37620 -1.10618 -0.37411 0.73780 
2000-01-28 -1.40276 1.98372 1.47096 -1.38043 
2000-01-31 0.54769 0.44100 -0.52775 0.84497 
2000-02-01 0.12443 0.32880 -0.71361 1.31778 
2000-02-02 -0.28986 -0.63931 0.88333 -2.58943 
2000-02-03 0.54408 1.17928 -0.26795 -0.51681 
2000-02-04 -0.07068 -1.29168 -0.59877 -1.45639 
2000-02-07 -0.65483 -0.29584 -0.02722 0.31270 
2000-02-08 -0.18529 -0.18701 -0.59132 -1.15239 
2000-02-09 -2.28496 0.36352 1.11596 0.02293 
2000-02-10 0.51054 0.97249 1.74501 0.20525 
2000-02-11 0.10100 0.27722 0.65843 1.73591 

In [12]: df[(df.values > 1.5).any(1)] 
Out[12]: 
      A  B  C  D  
2000-01-05 2.8021 -0.1086 -1.62114 -0.2017 
2000-01-06 0.7167 -0.2671 1.36029 1.7425 
2000-01-12 -0.3230 0.6233 1.93595 0.7802 
2000-01-13 1.7468 -1.5774 -0.02134 0.1160 
2000-01-14 -0.5561 0.9215 -0.22832 1.5663 
2000-01-20 1.5644 0.6233 -0.26904 0.1195 
2000-01-28 -1.4028 1.9837 1.47096 -1.3804 
2000-02-10 0.5105 0.9725 1.74501 0.2052 
2000-02-11 0.1010 0.2772 0.65843 1.7359 

Nhiều điều kiện phải được kết hợp sử dụng & hoặc | (và dấu ngoặc đơn!):

In [13]: df[(df['A'] > 1) | (df['B'] < -1)] 
Out[13]: 
      A  B  C  D  
2000-01-05 2.80215 -0.1086 -1.62114 -0.2017 
2000-01-13 1.74683 -1.5774 -0.02134 0.1160 
2000-01-20 1.56441 0.6233 -0.26904 0.1195 
2000-01-27 1.37620 -1.1062 -0.37411 0.7378 
2000-02-04 -0.07068 -1.2917 -0.59877 -1.4564 

Tôi rất muốn có một số loại API truy vấn để làm cho các loại điều này dễ dàng hơn

+1

Cảm ơn một lần nữa.Đừng đăng câu hỏi trong tương lai vào danh sách gửi thư. Nhưng bây giờ, nếu bạn muốn làm điều này theo chương trình thì sao? Bạn có một danh sách các nhãn cột ... làm thế nào bạn có thể nhận được điều đó vào '|' ký hiệu? Ví dụ. nếu 'nhãn = ['A', 'B', 'C', ... ']' – user248237dfsf

+0

Để làm rõ: Cách tiếp cận 'bất kỳ (1)' sẽ không hoạt động nếu bạn có các giá trị khác trong bảng mà bạn đã làm không muốn lọc. Giả sử có nhiều cột và bạn chỉ muốn 'any' để áp dụng cho một tập con của chúng (bạn biết nhãn của tập hợp con). – user248237dfsf

5

Có ít nhất một số phương pháp để rút ngắn cú pháp cho Pandas, cho đến khi nó nhận được API truy vấn đầy đủ đường (perhap s Tôi sẽ cố gắng tham gia dự án github và làm điều này là giấy phép thời gian và nếu không ai khác đã bắt đầu).

Một phương pháp để rút ngắn cú pháp một chút được đưa ra dưới đây:

inds = df.apply(lambda x: x["A"]>10 and x["B"]<5, axis=1) 
print df[inds].to_string() 

Để giải quyết đầy đủ này, người ta sẽ cần phải xây dựng một cái gì đó giống như SQL chọn và nơi điều khoản vào Pandas. Đây không phải là tầm thường chút nào, nhưng một lỗi mà tôi nghĩ có thể làm việc cho điều này là sử dụng mô-đun tích hợp Python operator. Điều này cho phép bạn đối xử với những thứ như lớn hơn chức năng thay vì biểu tượng. Vì vậy, bạn có thể làm như sau:

def pandas_select(dataframe, select_dict): 

    inds = dataframe.apply(lambda x: reduce(lambda v1,v2: v1 and v2, 
          [elem[0](x[key], elem[1]) 
          for key,elem in select_dict.iteritems()]), axis=1) 
    return dataframe[inds] 

Sau đó, một ví dụ thử nghiệm như của bạn sẽ được thực hiện như sau:

import operator 
select_dict = { 
       "A":(operator.gt,10), 
       "B":(operator.lt,5)     
       } 

print pandas_select(df, select_dict).to_string() 

Bạn có thể rút ngắn cú pháp hơn nữa bằng một trong hai tòa nhà ở đối số hơn để pandas_select để xử lý các toán tử logic khác nhau một cách tự động, hoặc bằng cách nhập chúng vào không gian tên với các tên ngắn hơn.

Lưu ý rằng hàm pandas_select ở trên chỉ hoạt động với các ràng buộc logic và chuỗi. Bạn sẽ phải sửa đổi nó để có được hành vi logic khác nhau. Hoặc sử dụng not và Luật của DeMorgan.

+0

Nếu tôi có danh sách ['Alice', 'Bob', 'Carl'] làm cách nào tôi có thể tạo từ điển để chọn các mục có dataframe ['A'] trong danh sách của tôi? –

+1

Nếu danh sách là 'a = ['Alice', 'Bob', 'Carl']' và khung dữ liệu tổng thể được gọi là 'df', thì bạn có thể làm điều này:' df [df.A.isin (a) ] 'và nó sẽ chọn phụ các chỉ mục hàng trong đó điều kiện thành viên thiết lập là đúng cho các phần tử của cột' A'. Mở rộng ngôn ngữ cụ thể của miền nhỏ mà tôi đã thực hiện ở trên để thể hiện các lôgic để có tùy chọn này với cú pháp đơn giản có thể sẽ là một công việc khó chịu. – ely

+0

có lẽ cũng thấy phương thức truy vấn sắp tới (gấu trúc 0,13): http://pandas.pydata.org/pandas-docs/dev/indexing.html?highlight=query#the-query-method-experimental và cũng http : //stackoverflow.com/questions/18521037/pandas-iterative-filtering-a-dataframes-rows – RuiDC

1

Một tính năng truy vấn đã được thêm vào Pandas vì câu hỏi này đã được hỏi và trả lời. Một ví dụ được đưa ra dưới đây.

Với khung dữ liệu mẫu này:

periods = 8 
dates = pd.date_range('20170101', periods=periods) 
rand_df = pd.DataFrame(np.random.randn(periods,4), index=dates, 
     columns=list('ABCD')) 

Cú pháp truy vấn như sau sẽ cho phép bạn sử dụng nhiều bộ lọc, giống như một "WHERE" khoản trong một tuyên bố chọn.

rand_df.query("A < 0 or B < 0") 

Xem chi tiết Pandas documentation để biết thêm chi tiết.

Các vấn đề liên quan