Bài 18: Data Selection và Indexing trong Pandas – p2 – Python Panda

Trang chủ » Training » Bài 18: Data Selection và Indexing trong Pandas – p2 – Python Panda
22/02/2022 Training 9 viewed

2. Data Selection và Indexing trong DataFrame

Cũng giống như Series và đã nhắc ở bài trước, với DataFrame thì ta sẽ hình dung nó như là một mảng 2 chiều hoặc như structured array trong NumPy.
Ngoài ra, ta có thể xem DataFrame giống như là một dictionary chứa các series có chung index với nhau (khá là giống với excel). Ta sẽ tìm hiểu từng trường hợp cụ thể sau:
a. DataFrame là Dictionary
Quay lại với ví dụ ở bài 2, ta có một DataFrame chứa các Series là dữ liệu dân số và diện tích của một số tỉnh / thành phố ở Việt Nam sau:
population = pd.Series({'TP.HCM': 8993, 'Hanoi': 8053, 'Lam Dong': 1297, 'Quang Tri': 623})
area = pd.Series({'TP.HCM': 2061, 'Hanoi': 3359, 'Lam Dong': 9765, 'Quang Tri': 4746})
 
data = pd.DataFrame({'Dân số': population, 'Diện tích': area})
 
data
Kết quả :
Dân số    Diện tích
TP.HCM         8993 2061
Hanoi          8053 3359
Lam Dong       1297 9765
Quang Tri   623 4746
Từng Series trong DataFrame có thể được truy cập theo kiểu dictionary bằng cách index vào tên của cột tương ứng:
data['Dân số']
TP.HCM       8993
Hanoi        8053
Lam Dong     1297
Quang Tri     623
Name: Dân số, dtype: int64
Ngoài cách trên, pandas cho phép ta truy cập trực tiếp vào các Series như là một thuộc tính của object:
data['population'] = data['Dân số']
 
data.population
TP.HCM       8993
Hanoi        8053
Lam Dong     1297
Quang Tri     623
Name: population, dtype: int64
Và ta cũng có thể thêm các cặp dữ liệu mới bằng cách tương tự như Series:
data['Mật độ'] = data['Dân số'] / data['Diện tích']
 
data
Kết quả :
Dân số    Diện tích   Mật độ
TP.HCM     8993             2061    4.363416
Hanoi       8053        3359    2.397440
Lam Dong    1297        9765    0.132821
Quang Tri    623        4746    0.131268
2. DataFrame là mảng 2 chiều
Với cách hình dung DataFrame là mảng 2 chiều thì cũng giống như Series là mảng 1 chiều, ta sẽ có một mảng 2 chiều hoạt động khá tương tự với NumPy. Chẳng hạn muốn lấy dữ liệu thô thì ta có thể truy cập qua thuộc tính values:
data.values
array([[8.99300000e+03, 2.06100000e+03, 4.36341582e+00],
       [8.05300000e+03, 3.35900000e+03, 2.39743971e+00],
       [1.29700000e+03, 9.76500000e+03, 1.32821301e-01],
       [6.23000000e+02, 4.74600000e+03, 1.31268437e-01]])
Nếu muốn lấy mảng chuyển vị (hoán đổi cột và hàng), ta có thể truy cập vào thuộc tính T (viết tắt cho transpose):
data.T
TP.HCM  Hanoi  Lam Dong  Quang Tri
Dân số       8993   8053      1297        623
Diện tích    2061   3359      9765       4746
Như vậy ta có thể thấy rằng sẽ có 2 cách để lấy mảng dữ liệu (dạng NumPy) từ một cột trong Pandas như sau:
print("Sdng chuyn vị: ", data.T.values[0])
print("Sdng index: ", data['Dân số'].values)
Sử dụng chuyển vị:  [8993. 8053. 1297.  623.]
Sử dụng index:  [8993 8053 1297  623]
c. Indexing trong DataFrame
Giống với Series, ta sẽ sử dụng 2 thuộc tính là loc và iloc. Với iloc, ta sẽ thao tác không khác gì một mảng 2 chiều trong NumPy với các hàng và cột tương ứng vậy, chẳng hạn:
print(data)
 
# Lấy hàng đầu tiên
print("\nDữ liệu của TP.HCM:\n ",data.iloc[0])
 
# Lấy dữ liệu 3 hàng đầu tiên
print("\nDữ liệu của TP.HCM, Hà Nội và Lâm Đồng:\n ",data.iloc[:3])
 
# Lấy dữ liệu 2 hàng và 2 cột đầu tiên
print("\nDữ liệu dân số và diện tích của TP.HCM và Hà Nội:\n ",data.iloc[:2, :2])
 
# Lấy dữ liệu tất ccác hàng và cột cuối cùng
print("\nMật độ dân số của các tỉnh / thành phố:\n ",data.iloc[:, -1])
Dân số  Diện tích    Mật độ
TP.HCM       8993       2061  4.363416
Hanoi        8053       3359  2.397440
Lam Dong     1297       9765  0.132821
Quang Tri     623       4746  0.131268
 
Dữ liệu của TP.HCM:
Dân số       8993.000000
Diện tích    2061.000000
Mật độ          4.363416
Name: TP.HCM, dtype: float64
 
Dữ liệu của TP.HCM,  Nội  Lâm Đồng:
            Dân số  Diện tích    Mật độ
TP.HCM      8993       2061  4.363416
Hanoi       8053       3359  2.397440
Lam Dong    1297       9765  0.132821
 
Dữ liệu dân số  diện tích của TP.HCM   Nội:
          Dân số  Diện tích
TP.HCM    8993       2061
Hanoi     8053       3359
 
Mật độ dân số của các tỉnh / thành phố:
TP.HCM       4.363416
Hanoi        2.397440
Lam Dong     0.132821
Quang Tri    0.131268
Name: Mật độ, dtype: float64
Với thuộc tính loc thì ta cũng sử dụng tương tự, nhưng thay vì với implicit index thì ta sử dụng với explicit index tương ứng:
print(data)
 
# Lấy hàng đầu tiên
print("\nDữ liệu của Quảng Trị:\n ",data.loc['Quang Tri'])
 
# Lấy dữ liệu 3 hàng đầu tiên
print("\nDữ liệu của TP.HCM, Hà Nội và Lâm Đồng:\n ",data.loc[:'Lam Dong'])
 
# Lấy dữ liệu 2 hàng và 2 cột đầu tiên
print("\nDữ liệu dân số và diện tích của TP.HCM và Hà Nội:\n ",data.loc[:'Hanoi', :'Diện tích'])
 
# Lấy dữ liệu tất cả các hàng và cột cuối cùng
print("\nMật độ dân số của các tỉnh / thành phố:\n ",data.loc[:, 'Mật độ'])
Dân số  Diện tích    Mật độ
TP.HCM       8993       2061  4.363416
Hanoi        8053       3359  2.397440
Lam Dong     1297       9765  0.132821
Quang Tri     623       4746  0.131268
 
Dữ liệu của Quảng Trị:
Dân số        623.000000
Diện tích    4746.000000
Mật độ          0.131268
Name: Quang Tri, dtype: float64
 
Dữ liệu của TP.HCM,  Nội  Lâm Đồng:
            Dân số  Diện tích    Mật độ
TP.HCM      8993       2061  4.363416
Hanoi       8053       3359  2.397440
Lam Dong    1297       9765  0.132821
 
Dữ liệu dân số  diện tích của TP.HCM   Nội:
          Dân số  Diện tích
TP.HCM    8993       2061
Hanoi     8053       3359
 
Mật độ dân số của các tỉnh / thành phố:
TP.HCM       4.363416
Hanoi        2.397440
Lam Dong     0.132821
Quang Tri    0.131268
Name: Mật độ, dtype: float64
Ta có thể kết hợp hai tính năng quan trọng trong NumPy là Masks và Fancy Indexing để tạo ra những câu truy vấn phức tạp hơn, ví dụ như:
print("\nDân số và mật độ của các tỉnh / TP có diện tích > 4000km2:\n", data.loc[data['Diện tích'] > 4000, ['Dân số', 'Mật độ']])
 
print("\nDiện tích của các tỉnh / TP có mật độ < 1000 người/km2 và dân số < 1 triệu người:\n", data.loc[(data['Mật độ'] < 1) & (data['Dân số'] < 1000), ['Dân số', 'Mật độ']])
Dân số  mật độ của các tỉnh / TP  diện tích > 4000km2:
            Dân số    Mật độ
Lam Dong     1297  0.132821
Quang Tri     623  0.131268
 
Diện tích của các tỉnh / TP  mật độ < 1000 người/km2  dân số < 1 triệu người:
            Dân số    Mật độ
Quang Tri     623  0.131268
Và ta cũng có thể sử dụng bất kỳ thuộc tính nào trong 2 thuộc tính trên để thay đổi giá trị trong DataFrame:
# Thay đổi dữ liệu mật độ dân số của tỉnh Quảng Trị bằng iloc
data.iloc[3, 2] = 1312
 
print("\nDữ liệu tỉnh Quảng Trị được cập nhật: \n", data)
 
# Thay đổi dữ liệu dân số của tỉnh Lâm Đồng bằng loc
data.loc['Lam Dong', 'Dân số'] = 1312
 
print("\nDữ liệu tỉnh Lâm Đồng được cập nhật: \n", data)
Dữ liệu tỉnh Quảng Trị được cập nhật: 
            Dân số  Diện tích       Mật độ
TP.HCM       8993       2061     4.363416
Hanoi        8053       3359     2.397440
Lam Dong     1312       9765     0.132821
Quang Tri     623       4746  1312.000000
 
Dữ liệu tỉnh Lâm Đồng được cập nhật: 
            Dân số  Diện tích       Mật độ
TP.HCM       8993       2061     4.363416
Hanoi        8053       3359     2.397440
Lam Dong     1312       9765     0.132821
Quang Tri     623       4746  1312.000000
Có một vài quy ước trong Pandas không hoàn toàn giống NumPy và ta nên nắm rõ vì nó khá hữu dụng trong thực tế. Đầu tiên đó là indexing thường chỉ đến cột, còn slicing thường dành cho hàng:
# Indexing 
print("Indexing: \n", data['Dân số'])
 
# Slicing
print("\nSlicing: \n",data['Hanoi':'Quang Tri'])
Indexing: 
TP.HCM       8993
Hanoi        8053
Lam Dong     1312
Quang Tri     623
Name: Dân số, dtype: int64
 
Slicing: 
            Dân số  Diện tích       Mật độ
Hanoi        8053       3359     2.397440
Lam Dong     1312       9765     0.132821
Quang Tri     623       4746  1312.000000
Tiếp theo, nếu như dùng slicing thì pandas sẽ mặc định tham chiếu đến implicit index:
print(data[0:2])
Dân số  Diện tích    Mật độ
TP.HCM    8993       2061  4.363416
Hanoi     8053       3359  2.397440
Và cuối cùng, tương tự slicing thì masking sẽ tham chiếu đến hàng tương ứng thay vì cột:
print(data[data['Dân số'] > 1000])
Dân số  Diện tích    Mật độ
TP.HCM      8993       2061  4.363416
Hanoi       8053       3359  2.397440
Lam Dong    1312       9765  0.132821
Chia sẻ:
Tags:
TOP HOME