2013-03-09 30 views
106

Ví dụ tôi có đơn giản DF:Lựa chọn với tiêu chí phức tạp từ pandas.DataFrame

import pandas as pd 
from random import randint 

df = pd.DataFrame({'A': [randint(1, 9) for x in xrange(10)], 
        'B': [randint(1, 9)*10 for x in xrange(10)], 
        'C': [randint(1, 9)*100 for x in xrange(10)]}) 

Tôi có thể chọn các giá trị từ 'A' mà giá trị tương ứng cho 'B' sẽ lớn hơn 50, và cho ' C '- không bằng 900, sử dụng các phương pháp và thành ngữ của Pandas?

+0

Bình chọn cho tên của bạn! – 8090PZ

Trả lời

196

Chắc chắn! Setup:

>>> import pandas as pd 
>>> from random import randint 
>>> df = pd.DataFrame({'A': [randint(1, 9) for x in xrange(10)], 
        'B': [randint(1, 9)*10 for x in xrange(10)], 
        'C': [randint(1, 9)*100 for x in xrange(10)]}) 
>>> df 
    A B C 
0 9 40 300 
1 9 70 700 
2 5 70 900 
3 8 80 900 
4 7 50 200 
5 9 30 900 
6 2 80 700 
7 2 80 400 
8 5 80 300 
9 7 70 800 

Chúng ta có thể áp dụng các hoạt động cột và nhận boolean đối tượng Series:

>>> df["B"] > 50 
0 False 
1  True 
2  True 
3  True 
4 False 
5 False 
6  True 
7  True 
8  True 
9  True 
Name: B 
>>> (df["B"] > 50) & (df["C"] == 900) 
0 False 
1 False 
2  True 
3  True 
4 False 
5 False 
6 False 
7 False 
8 False 
9 False 

[Update, để chuyển sang kiểu mới .loc]:

Và sau đó chúng ta có thể sử dụng chúng để chỉ mục vào đối tượng. Để truy cập đọc, bạn có thể chuỗi chỉ mục:

>>> df["A"][(df["B"] > 50) & (df["C"] == 900)] 
2 5 
3 8 
Name: A, dtype: int64 

nhưng bạn có thể gặp rắc rối vì sự khác biệt giữa chế độ xem và bản sao làm việc này để ghi quyền truy cập. Bạn có thể sử dụng thay vì .loc:

>>> df.loc[(df["B"] > 50) & (df["C"] == 900), "A"] 
2 5 
3 8 
Name: A, dtype: int64 
>>> df.loc[(df["B"] > 50) & (df["C"] == 900), "A"].values 
array([5, 8], dtype=int64) 
>>> df.loc[(df["B"] > 50) & (df["C"] == 900), "A"] *= 1000 
>>> df 
     A B C 
0  9 40 300 
1  9 70 700 
2 5000 70 900 
3 8000 80 900 
4  7 50 200 
5  9 30 900 
6  2 80 700 
7  2 80 400 
8  5 80 300 
9  7 70 800 

Lưu ý rằng tôi vô tình đã làm == 900 và không != 900, hoặc ~(df["C"] == 900), nhưng tôi quá lười biếng để sửa chữa nó. Tập thể dục cho người đọc. : ^)

+0

Thật tuyệt vời! Cảm ơn rất nhiều! –

+4

Làm cách nào để ghi đè (cập nhật) các hàng thu được bằng cách chọn? –

+0

Giới thiệu về bản cập nhật '.loc' - sẽ tốt nếu bạn làm rõ nơi chúng tôi nhận được bản sao và nơi xem. –

10

Một giải pháp khác là sử dụng các phương pháp query:

import pandas as pd 

from random import randint 
df = pd.DataFrame({'A': [randint(1, 9) for x in xrange(10)], 
        'B': [randint(1, 9) * 10 for x in xrange(10)], 
        'C': [randint(1, 9) * 100 for x in xrange(10)]}) 
print df 

    A B C 
0 7 20 300 
1 7 80 700 
2 4 90 100 
3 4 30 900 
4 7 80 200 
5 7 60 800 
6 3 80 900 
7 9 40 100 
8 6 40 100 
9 3 10 600 

print df.query('B > 50 and C != 900') 

    A B C 
1 7 80 700 
2 4 90 100 
4 7 80 200 
5 7 60 800 

Bây giờ nếu bạn muốn thay đổi các giá trị trả lại trong cột A bạn có thể lưu chỉ mục của họ:

my_query_index = df.query('B > 50 & C != 900').index 

.. ..và sử dụng .iloc để thay đổi chúng, ví dụ:

df.iloc[my_query_index, 0] = 5000 

print df 

     A B C 
0  7 20 300 
1 5000 80 700 
2 5000 90 100 
3  4 30 900 
4 5000 80 200 
5 5000 60 800 
6  3 80 900 
7  9 40 100 
8  6 40 100 
9  3 10 600 
Các vấn đề liên quan