Bài 17: Data Selection và Indexing trong Pandas - p1 - Python Panda

Đăng bởi: Admin | Lượt xem: 1700 | Chuyên mục: Python


Trong bài này chúng ta sẽ tìm hiểu Data Selection và Indexing trong Pandas, thông qua hai đối tượng DataFrame và Series.
Trong chương NumPy, chúng ta đã tìm hiểu các cách để truy cập vào các phần tử / mảng con như:
  • indexing (vd: arr[2]),
  • slicing (vd: arr[:, 2]),
  • masking (vd: arr[arr % 2 == 0),
  • fancy indexing (vd: arr[[2, 1, 5]])
  • và kết hợp các kiểu trên (vd: arr[[1, 2, 5], :]).
Vì Pandas được xây dựng từ NumPy, nên cách truy cập và chỉnh sửa giá trị phần tử của 2 thư viện không khác nhau mấy, nếu bạn đã làm quen với NumPy thì sẽ khá dễ để làm quen. Dù vậy, sẽ có một số sự khác biệt mà trong bài mình sẽ đề cập đến

1. Data Selection và Indexing trong Series

Như mình đã nói ở bài trước, ta có thể hình dung Series trong Pandas chính là mảng 1 chiều trong NumPy hoặc là Dictionary trong Python, từ các cách hiểu đó thì ta sẽ đi xem xét từng trường hợp cụ thể:
a. Series là Dictionary
Giống như Dictionary, Series cho phép ta map các cặp key - value tương ứng với nhau:
data = pd.Series([1, 2, 3, 4], index=['a', 'b', 'c', 'd'])
 
data['a']
Kết quả :
1
Ngoài ra ta còn có thể sử dụng một số biểu thức của Dictionary như sau:
print("'c' trong data: ", 'c' in data)
print("keys: ", data.keys())
print("values: ", list(data.items()))
Kết quả :
'c' trong data:  True
keys:  Index(['a', 'b', 'c', 'd'], dtype='object')
values:  [('a', 1), ('b', 2), ('c', 3), ('d', 4)]
Tương tự như Dictionary, bạn hoàn toàn có thể thêm 1 giá trị mới vào series bằng cách gán một cặp key - value tương ứng:
data['freetuts'] = 9999
 
data
Kết quả :
a              1
b              2
c              3
d              4
freetuts    9999
dtype: int64
Pandas sẽ đưa ra quyết định về bố trí bộ nhớ cũng như cách xử lý nó và chúng ta hầu như không cần quan tâm về vấn đề này. Đây là một trong những điểm rất tiện dụng của Pandas.
b. Series là mảng 1 chiều
Với cách hình dung series là mảng 1 chiều, ta sẽ thao tác với nó không khác việc thao tác với NumPy là mấy, ta sẽ tìm hiểu một số thao tác cơ bản:

Array Slicing

Array slicing trong Series tương tự như NumPy, tuy nhiên có 2 kiểu slicing, đầu tiên là slicing với index chỉ định (explicit index - nhãn của các phần tử trong dãy):
# Array slicing, lấy giá trị trong khoảng index từ a -> c
data['a': 'c']
Kết quả :
a    1
b    2
c    3
dtype: int64
Thứ 2 là slicing với index ngầm định (implicit index - vị trí của các phần tử trong dãy), chẳng hạn với ví dụ trên, ta có slicing tương tự sau:
# Array Slicing, lấy giá trị trong khoảng index từ 0 -> 3
data[0:3]
Kết quả :
a    1
b    2
c    3
dtype: int64
Đây cũng là điểm cần lưu ý trong Pandas, đó là khi ta dùng slicing với index thì cặp index và giá trị tương ứng cuối cùng sẽ được trả về (cụ thể ở ví dụ trên là c - 3), trong khi nếu như sử dụng với index ngầm định thì không:
# Lấy phần tử có index là 0 và 1, không lấy 2
data[0:2]
Kết quả :
a    1
b    2
dtype: int64

Array masking

Cũng tương tự như trong NumPy, ta có thể sử dụng masks lên series như sau:
# Lấy các hàng chia hết cho 3
data[data % 3 == 0]
Kết quả :
c              3
freetuts    9999
dtype: int64

Fancy Indexing

Giống như array slicing, ta có 2 kiểu fancy indexing, đó là sử dụng với explicit index:
# explicit index
data[['b', 'd']]
b    2
d    4
dtype: int64
Và với implicit index:
# implicit index
data[[1, 4]]
Kết quả :
b              2
freetuts    9999
dtype: int64
c. Indexing trong Series
Có thể thấy rằng explicit index và implicit index khá là dễ nhầm lẫn với nhau, mình có một ví dụ minh hoạ như sau:
data = pd.Series(['F', 'r', 'e', 'e', 't', 'u', 't', 's'], index=[1, 3, 5, 6, 7, 9, 10, 12])
 
print("Data: ", data)
 
# explicit index
print("data[1]: ", data[1])
 
# implicit index 
print("data[0:5]: ", data[1:3])
Kết quả :
Data: 
1     F
3     r
5     e
6     e
7     t
9     u
10    t
12    s
dtype: object
 
data[1]:  F
data[0:5]:  
3    r
5    e
dtype: object
Ảnh sau mô tả quan hệ giữa implicit index và explicit index:
Vì điều này nên Pandas cung cấp cho ta một số thuộc tính được gọi là indexers gồm loc, iloc và ix, các thuộc tính này sẽ cho phép ta biết được ta đang sử dụng loại index gì mà không bị nhầm lẫn.
Đầu tiên là loc, thuộc tính này cho phép chúng ta indexing và slicing bằng explicit index:
print("Lấy giá trị có index tương ứng là 1:", data.loc[1])
 
print("Lấy khoảng giá trị có index nằm trong khoảng [1, 6]:", data.loc[1:6])
Lấy giá trị có index tương ứng là 1: F
 
Lấy khoảng giá trị có index nằm trong khoảng [1, 6]: 
1    F
3    r
5    e
6    e
dtype: object
Còn iloc thì tương tự như loc nhưng là với implicit index:
# Implicit index = 1 tương ứng với vị trí thứ 2 trong mảng
print("Lấy giá trị có implicit index = 1:", data.iloc[1])
 
# Implicit index = [1,6] tương ứng với vị trí thứ 1, 2, 3, 4, 5 trong mảng
print("Lấy khoảng giá trị có implicit index nằm trong khoảng [1, 6]:", data.iloc[1:6])
Lấy giá trị có implicit index = 1: r
Lấy khoảng giá trị có implicit index nằm trong khoảng [1, 6]:
3    r
5    e
6    e
7    t
9    u
dtype: object
Với ix thì nó sẽ là sự kết hợp của cả 2 thuộc tính trên, và nó cũng không khác gì với việc ta indexing truyền thống - dễ gây nhầm lẫn khi sử dụng 2 kiểu index trên, do vậy nên từ phiên bản pandas 0.20.0, thuộc tính ix đã deprecated và không còn khuyến khích sử dụng nữa. Vì vậy trong bài này và trong series pandas nói chung, mình sẽ không đề cập đến thuộc tính này.
Bài tiếp theo: Data Selection và Indexing trong Pandas - p2 >>
vncoder logo

Theo dõi VnCoder trên Facebook, để cập nhật những bài viết, tin tức và khoá học mới nhất!