Chương 5 Chọn và lọc dữ liệu trong DataFame

5.1 Sử dụng []

Cú pháp [] là cú pháp đơn giản nhất để lấy bảng con của 1 bảng cho trước. Với 1 df là 1 DataFrame có index là region và dữ liệu như sau

                         state  individuals  family_members  state_pop
region                                                                
East South Central     Alabama       2570.0           864.0    4887681
Pacific                 Alaska       1434.0           582.0     735139
Mountain               Arizona       7259.0          2606.0    7158024
West South Central    Arkansas       2280.0           432.0    3009733
Pacific             California     109008.0         20964.0   39461588
Mountain              Colorado       7607.0          3250.0    5691287

Để chọn 1 bảng con có 2 cột ['state', 'family_members'] ta làm như sau

df[['state', 'family_members']]
                         state  family_members
region                                        
East South Central     Alabama           864.0
Pacific                 Alaska           582.0
Mountain               Arizona          2606.0
West South Central    Arkansas           432.0
Pacific             California         20964.0
Mountain              Colorado          3250.0

Để lấy theo dòng ta dùng tương tự Series

df[:3]
                      state  individuals  family_members  state_pop
region                                                             
East South Central  Alabama       2570.0           864.0    4887681
Pacific              Alaska       1434.0           582.0     735139
Mountain            Arizona       7259.0          2606.0    7158024
df[2:5]
                         state  individuals  family_members  state_pop
region                                                                
Mountain               Arizona       7259.0          2606.0    7158024
West South Central    Arkansas       2280.0           432.0    3009733
Pacific             California     109008.0         20964.0   39461588

Lưu ý:

  • df[['state']] sẽ trả về DataFrame trong khi df['state'] trả về Series.

  • Đối với lấy theo dòng, [] không lấy được theo dòng riêng biệt.

  • [] chỉ lấy dữ liệu theo dòng hoặc cột, không thực hiện được cùng lúc cả hai thao tác.

Ví dụ khi gọi df[3] hay df[[1, 2, 3]] sẽ báo lỗi KeyError

5.2 Sử dụng .loc

Phương thức .loc dùng để lấy dữ liệu theo cột hoặc hàng dựa theo nhãn định sẵn (Tên hàng, tên cột), ngoài ra .loc còn nhận các giá trị boolean.

Đầu vào của .loc có thể gồm:

  • Nhãn đơn: là 1 số 3 hoặc dạng chữ a, lưu ý rằng số này là nhãn của index chứ không phải vị trí của dòng.

  • Danh sách các nhãn : ['a', 'b', 'c']

  • Đối tượng dạng slice ví dụ 'a':'e'

  • Danh sách kiểu bool có độ dài bằng với số lượng dòng

  • Series dạng bool

  • pd.Index

Sử dụng nhãn đơn, kết quả trả về là các dòng có nhãn giống như nhãn trong .loc

df.loc['Pacific']
              state  individuals  family_members  state_pop
region                                                     
Pacific      Alaska       1434.0           582.0     735139
Pacific  California     109008.0         20964.0   39461588

Lưu ý:

Khi kết quả là nhiều dòng thì dữ liệu trả về có kiểu DataFrame, trong khi nếu chỉ có 1 dòng duy nhất thì kết quả trả về sẽ theo kiểu Series
type(df.loc['Pacific'])
<class 'pandas.core.frame.DataFrame'>
type(df.loc['West South Central'])
<class 'pandas.core.series.Series'>

Khi đưa danh sách các nhãn dùng .loc[[]] thì nhãn đưa vào là nhãn của index. Nếu đưa tên các cột sẽ bị báo lỗi KeyError

df.loc[['Pacific', 'Mountain']]
               state  individuals  family_members  state_pop
region                                                      
Pacific       Alaska       1434.0           582.0     735139
Pacific   California     109008.0         20964.0   39461588
Mountain     Arizona       7259.0          2606.0    7158024
Mountain    Colorado       7607.0          3250.0    5691287

Để lấy nhãn đơn theo nhãn của index và tên column ta truyền vào phần nhãn của index trước và nhãn của column sau và phân biệt bởi dấu phẩy

df.loc['Pacific', 'state']
region
Pacific        Alaska
Pacific    California
Name: state, dtype: object

Để lấy nhiều hơn 1 nhãn của index hoặc nhiều hơn 1 nhãn của column ta chỉ cần thay thế nhãn đơn của index thành danh sách hoặc slice, tương tự ta có thế thay thế nhãn đơn thành danh sách hoặc slice của column

df.loc['Pacific', ['individuals', 'family_members']])
         individuals  family_members
region                              
Pacific       1434.0           582.0
Pacific     109008.0         20964.0
df.loc['Pacific', 'individuals':'state_pop']
         individuals  family_members  state_pop
region                                         
Pacific       1434.0           582.0     735139
Pacific     109008.0         20964.0   39461588

Lưu ý:

  • Dùng slice sẽ lấy theo thứ tự xuất hiện chứ không lấy theo thứ tự sắp xếp từ điển, như ví dụ trên thì mặc dù family_members > individuals nhưng vẫn xếp sau.

  • Slice không áp dụng được cho index có nhãn trùng nhau, nếu dùng sẽ báo lỗi KeyError: "Cannot get right slice bound for non-unique label:

Danh sách dạng boolean, chỉ sử dụng cho index, không dùng cho column

df.loc[[False, True, False, True, False, False]]
                       state  individuals  family_members  state_pop
region                                                              
Pacific               Alaska       1434.0           582.0     735139
West South Central  Arkansas       2280.0           432.0    3009733

Series boolean

s = pd.Series([False, True, False, True, False, False],
              index=['East South Central', 'Pacific', 'Mountain', 'West South Central', 'Pacific', 'Mountain'])
df.loc[s]
                       state  individuals  family_members  state_pop
region                                                              
Pacific               Alaska       1434.0           582.0     735139
West South Central  Arkansas       2280.0           432.0    3009733

pd.Index

df.loc[pd.Index(["Pacific", "East South Central"], name="meow")]
                         state  individuals  family_members  state_pop
meow                                                                   
Pacific                 Alaska       1434.0           582.0     735139
Pacific             California     109008.0         20964.0   39461588
East South Central     Alabama       2570.0           864.0    4887681

Select với MultiIndex

                     individuals  family_members  state_pop
region   state                                             
Mountain Arizona          7259.0          2606.0    7158024
         Colorado         7607.0          3250.0    5691287
         Idaho            1297.0           715.0    1750536
Pacific  Alaska           1434.0           582.0     735139
         California     109008.0         20964.0   39461588
         Hawaii           4131.0          2399.0    1420593

Với nhãn đơn

df.loc['Mountain']
          individuals  family_members  state_pop
state                                           
Arizona        7259.0          2606.0    7158024
Colorado       7607.0          3250.0    5691287
Idaho          1297.0           715.0    1750536
Lưu ý: Với MultiIndex,các index sẽ xếp theo thứ tự từ level 0 đến n (level 0 cao hơn level 1 …), với nhãn đơn là nhãn của 1 index thì chỉ thực hiện được index level đầu tiên, các index level sau sẽ báo lỗi. Theo như ví dụ trên thì region có level cao hơn ‘state’ nên chỉ gọi được .loc['Mountain'] còn .loc['Arizona'] sẽ báo lỗi

Để select nhiều index cùng lúc, ta truyền vào tuple(label1, label2...) theo thứ tự index có level từ cao đến thấp

df.loc[('Mountain', 'Colorado')]
individuals          7607.0
family_members       3250.0
state_pop         5691287.0
Name: (Mountain, Colorado), dtype: float64

Tương tự ta cùng có select theo các column cho trước

df.loc[('Mountain', 'Colorado'), ['individuals', 'family_members']]
individuals       7607.0
family_members    3250.0
Name: (Mountain, Colorado), dtype: float64

Mẹo: Có thể select index ở các level sau bằng cách dùng slice

df.loc[(slice(None), 'Arizona'), :]
                  individuals  family_members  state_pop
region   state                                          
Mountain Arizona       7259.0          2606.0    7158024

Slice cho MultiIndex

Slice từ 1 tuple nhãn đến một nhãn đơn

df.loc[('Mountain', 'Colorado'):'Pacific']
                     individuals  family_members  state_pop
region   state                                             
Mountain Colorado         7607.0          3250.0    5691287
         Idaho            1297.0           715.0    1750536
Pacific  Alaska           1434.0           582.0     735139
         California     109008.0         20964.0   39461588
         Hawaii           4131.0          2399.0    1420593
Lưu ý: Nhãn đơn phía sau phải có cùng level với nhãn đầu tiên trong tuple. Trong ví dụ trên nếu thay Pacific thành Hawaii sẽ trả về rỗng. Nhưng khi truyền nhãn không nằm trong các nhãn của index thì vẫn có kết quả trả về
df.loc[('Mountain', 'Colorado'): 'meow']
                     individuals  family_members  state_pop
region   state                                             
Mountain Colorado         7607.0          3250.0    5691287
         Idaho            1297.0           715.0    1750536
Pacific  Alaska           1434.0           582.0     735139
         California     109008.0         20964.0   39461588
         Hawaii           4131.0          2399.0    1420593

Slice từ 1 tuple nhãn đến một tuple nhãn

df.loc[('Mountain', 'Colorado'):('Pacific', 'California')]
                     individuals  family_members  state_pop
region   state                                             
Mountain Colorado         7607.0          3250.0    5691287
         Idaho            1297.0           715.0    1750536
Pacific  Alaska           1434.0           582.0     735139
         California     109008.0         20964.0   39461588

5.3 Sử dụng .iloc

Phương thức .iloc dùng để lấy dữ liệu theo cột hoặc hàng dựa theo index của nó, ngoài ra .iloc còn nhận các giá trị boolean.

Đầu vào của .iloc có thể gồm:

  • Nhãn đơn: là 1 số 3

  • Danh sách các số : [1, 2, 3]

  • Đối tượng dạng slice ví dụ 1:5

  • Danh sách kiểu bool có độ dài bằng với số lượng dòng

Ví dụ với DataFrame

                         state  individuals  family_members  state_pop
region                                                                
East South Central     Alabama       2570.0           864.0    4887681
Pacific                 Alaska       1434.0           582.0     735139
Mountain               Arizona       7259.0          2606.0    7158024
West South Central    Arkansas       2280.0           432.0    3009733
Pacific             California     109008.0         20964.0   39461588
Mountain              Colorado       7607.0          3250.0    5691287

Khi truyền 1 giá trị nguyên, .iloc trả về giá trị của dòng tại vị trí truyền vào với kiểu Series

df.iloc[0]
state             Alabama
individuals        2570.0
family_members      864.0
state_pop         4887681
Name: East South Central, dtype: object
Lưu ý: Series trả về không chứa nhãn của index, ở đây là nhãn East South Central của index region

Để lấy dữ liệu theo cột, ví dụ muốn lấy cột family_members thì sẽ truyền index cột là 2

df.iloc[:, 2]
region
East South Central      864.0
Pacific                 582.0
Mountain               2606.0
West South Central      432.0
Pacific               20964.0
Mountain               3250.0
Name: family_members, dtype: float64

Mẹo:

  • .iloc bắt buộc truyền vào vị trí của cột, không cho phép tên cột.

  • Sử dụng .columns.get_loc(<tên cột>) để lấy vị trí của cột

df.iloc[:, df.columns.get_loc('family_members')]
region
East South Central      864.0
Pacific                 582.0
Mountain               2606.0
West South Central      432.0
Pacific               20964.0
Mountain               3250.0
Name: family_members, dtype: float64

Select theo danh sách, mặc định đưa vào 1 danh sách Pandas sẽ hiểu là lấy theo các dòng

df.iloc[[1, 3 ,5]]
                   individuals  family_members  state_pop
region   state                                           
Mountain Colorado       7607.0          3250.0    5691287
Pacific  Alaska         1434.0           582.0     735139
         Hawaii         4131.0          2399.0    1420593
Mẹo: Dòng lệnh trên cũng tương đương với df.iloc[[1, 3 ,5], :], trong đó : dùng để lấy toàn bộ

Tương tự để lấy theo danh sách index các cột

df.iloc[:, [0, 2]]
                     individuals  state_pop
region   state                             
Mountain Arizona          7259.0    7158024
         Colorado         7607.0    5691287
         Idaho            1297.0    1750536
Pacific  Alaska           1434.0     735139
         California     109008.0   39461588
         Hawaii           4131.0    1420593

Slice cả 2 chiều

df.iloc[2:4, 0:2]
                 individuals  family_members
region   state                              
Mountain Idaho        1297.0           715.0
Pacific  Alaska       1434.0           582.0

Sử dụng danh sách các boolean

# Theo dòng
df.iloc[[True, False, True, False, False, True], :]
                  individuals  family_members  state_pop
region   state                                          
Mountain Arizona       7259.0          2606.0    7158024
         Idaho         1297.0           715.0    1750536
Pacific  Hawaii        4131.0          2399.0    1420593
df.iloc[:, [False, True,False]]
                     family_members
region   state                     
Mountain Arizona             2606.0
         Colorado            3250.0
         Idaho                715.0
Pacific  Alaska               582.0
         California         20964.0
         Hawaii              2399.0

5.4 Lọc theo điều kiện

Các phương thức [], .loc hay .iloc ngoài việc lấy dữ liệu theo hàng và cột còn có thể lấy ra những bảng con theo các điều kiện cho trước. Bản chất các câu điều kiện sẽ trả về một danh sách dạng bolean và các hàm trên thực hiện lọc theo danh sách đó.

Trước hết ta cần biết câu điều kiện trong Pandas như thế nào. Ví dụ ta có 1 DataFrame như sau

               state  individuals  family_members  state_pop
region                                                      
Mountain     Arizona       7259.0          2606.0    7158024
Mountain    Colorado       7607.0          3250.0    5691287
Mountain       Idaho       1297.0           715.0    1750536
Pacific       Alaska       1434.0           582.0     735139
Pacific   California     109008.0         20964.0   39461588
Pacific       Hawaii       4131.0          2399.0    1420593

5.4.1 Toán tử điều kiện

Giả sử ta có một điều kiện rằng df['individuals'] > 5000. Kết quả trả về là 1 Series

df['individuals'] > 5000
region
Mountain     True
Mountain     True
Mountain    False
Pacific     False
Pacific      True
Pacific     False
Name: individuals, dtype: bool

Để lọc theo điều kiện này ta có các cách như sau

## Dùng []
df[df['individuals'] > 5000]
               state  individuals  family_members  state_pop
region                                                      
Mountain     Arizona       7259.0          2606.0    7158024
Mountain    Colorado       7607.0          3250.0    5691287
Pacific   California     109008.0         20964.0   39461588
## Dùng .loc
df.loc[df['individuals'] > 5000]
               state  individuals  family_members  state_pop
region                                                      
Mountain     Arizona       7259.0          2606.0    7158024
Mountain    Colorado       7607.0          3250.0    5691287
Pacific   California     109008.0         20964.0   39461588

Lưu ý: .iloc không nhận Series boolean nhưng array thì có thể. Do đó ta có thể dùng .values để lấy kết quả của Câu điều kiện

## Dùng .iloc
df.iloc[(df['individuals'] > 5000).values]
               state  individuals  family_members  state_pop
region                                                      
Mountain     Arizona       7259.0          2606.0    7158024
Mountain    Colorado       7607.0          3250.0    5691287
Pacific   California     109008.0         20964.0   39461588

Ta cũng có thể áp nhiều điều kiện cùng lúc, mỗi điều kiện phải nằm trong dấu ngoặc đơn () và giữa các kiều kiện là toán tử & hoặc |

## Nhiều câu điều kiện trên một cột
df.loc[(df['individuals'] > 5000) & (df['individuals'] < 10000)]
             state  individuals  family_members  state_pop
region                                                    
Mountain   Arizona       7259.0          2606.0    7158024
Mountain  Colorado       7607.0          3250.0    5691287
## Nhiều câu điều kiện ở nhiều cột
df.loc[(df['individuals'] > 5000) & (df['family_members'] < 10000)]
             state  individuals  family_members  state_pop
region                                                    
Mountain   Arizona       7259.0          2606.0    7158024
Mountain  Colorado       7607.0          3250.0    5691287
## Một câu điều kiện trên nhiều cột
df[df['individuals'] > 5 * df['family_members']]
              state  individuals  family_members  state_pop
region                                                     
Pacific  California     109008.0         20964.0   39461588
Mẹo: Bạn cũng có thể dùng loc để vừa lọc các dòng thỏa điều kiện, vừa chọn các cột muốn lấy
df.loc[df['individuals'] > 5 * df['family_members'], ['individuals', 'family_members']]
         individuals  family_members
region                              
Pacific     109008.0         20964.0

Ngoài ra, pandas còn cho phép bạn lọc với cấu trúc câu truy vấn bằng .query theo cú pháp

DataFrame.query(expr, inplace=False, **kwargs)

Trong đó:

  • expr: là câu truy vấn

  • inplace: thực hiện trên chính DataFrame đó hay tạo 1 bảng sao

  • **kwargs: keyword arguments

Theo ví dụ trên, để thực hiện lọc theo điều kiện df['individuals'] > 5000df['family_members'] < 10000 ta có thể làm như sau

df.query('individuals > 500 and family_members < 10000')
             state  individuals  family_members  state_pop
region                                                    
Mountain   Arizona       7259.0          2606.0    7158024
Mountain  Colorado       7607.0          3250.0    5691287

5.4.2 .isin()

Phương thức .isin(values) để kiểm tra các phần tử trong DataFrame hoặc Series có nằm trong values hay không.

Ví dụ:

df.isin(['Alaska', 'Oklahoma', 'Illinois', 'Arizona', 7259, 582, 300])
          state  individuals  family_members  state_pop
region                                                 
Mountain   True         True           False      False
Mountain  False        False           False      False
Mountain  False        False           False      False
Pacific    True        False            True      False
Pacific   False        False           False      False
Pacific   False        False           False      False
df['state'].isin(['Alaska', 'Oklahoma', 'Illinois', 'Arizona'])
region
Mountain     True
Mountain    False
Mountain    False
Pacific      True
Pacific     False
Pacific     False
Name: state, dtype: bool

Ngoài ra bạn có thể truyền values là một dictionary để kiểm tra cho từng cột theo từng tập giá trị

df.isin({'state': ['Alaska', 'Oklahoma', 'Illinois', 'Arizona'], 
         'individuals': [7259, 582, 300]})
          state  individuals  family_members  state_pop
region                                                 
Mountain   True         True           False      False
Mountain  False        False           False      False
Mountain  False        False           False      False
Pacific    True        False           False      False
Pacific   False        False           False      False
Pacific   False        False           False      False

Lọc với .isin()

df[df['state'].isin(['Alaska', 'Oklahoma', 'Illinois', 'Arizona'])]
            state  individuals  family_members  state_pop
region                                                   
Mountain  Arizona       7259.0          2606.0    7158024
Pacific    Alaska       1434.0           582.0     735139

trong trường hợp sự dụng .isin với DataFrame, kết quả của lọc sẽ trả về một DataFrame với giá trị các phần tử mà phép isin trả về True, các phần tử còn lại trả giá trị NaN

df[df.isin(['Alaska', 'Oklahoma', 'Illinois', 'Arizona', 7259, 582, 300])]
            state  individuals  family_members  state_pop
region                                                   
Mountain  Arizona       7259.0             NaN        NaN
Mountain      NaN          NaN             NaN        NaN
Mountain      NaN          NaN             NaN        NaN
Pacific    Alaska          NaN           582.0        NaN
Pacific       NaN          NaN             NaN        NaN
Pacific       NaN          NaN             NaN        NaN

Mẹo:

  • Bạn có dùng .any() để tổng hợp điều kiện của 1 DataFrame với các phần tử boolean

  • .any(axis=1) : Chỉ cần tồn tại 1 cột giá trị True, trả về giá trị True cho dòng

  • .any(axis=0): Chỉ cần tồn tại 1 dòng có giá trị True, trả về giá trị True cho cột.

  • Phương thức .any() thường dùng để kiểm tra các dòng tồn tại 1 cột giá trị NaN

Lọc với .isin()any(axis=1)

df.isin(['Alaska', 'Oklahoma', 'Illinois', 'Arizona', 7259, 582, 300]).any(axis=1)
region
Mountain     True
Mountain    False
Mountain    False
Pacific      True
Pacific     False
Pacific     False
dtype: bool
df[df.isin(['Alaska', 'Oklahoma', 'Illinois', 'Arizona', 7259, 582, 300]).any(axis=1)]
            state  individuals  family_members  state_pop
region                                                   
Mountain  Arizona       7259.0          2606.0    7158024
Pacific    Alaska       1434.0           582.0     735139

Lọc với isin()any(axis=0)

df.isin(['Alaska', 'Oklahoma', 'Illinois', 'Arizona', 7259, 582, 300]).any(axis=0)
state              True
individuals        True
family_members     True
state_pop         False
dtype: bool
df.loc[:,df.isin(['Alaska', 'Oklahoma', 'Illinois', 'Arizona', 7259, 582, 300]).any(axis=0)]
               state  individuals  family_members
region                                           
Mountain     Arizona       7259.0          2606.0
Mountain    Colorado       7607.0          3250.0
Mountain       Idaho       1297.0           715.0
Pacific       Alaska       1434.0           582.0
Pacific   California     109008.0         20964.0
Pacific       Hawaii       4131.0          2399.0

Lọc với isin()any(axis=0)any(axis=1)

bool_df = df.isin(['Alaska', 'Oklahoma', 'Illinois', 'Arizona', 7259, 582, 300])
df.loc[bool_df.any(axis=1), bool_df.any(axis=0)]
            state  individuals  family_members
region                                        
Mountain  Arizona       7259.0          2606.0
Pacific    Alaska       1434.0           582.0

5.4.3 Lọc missing value với .dropna()

Trong quá trình xử lý dữ liệu, chúng ta thường gặp những bảng có chứa giá trị missing value. Ví dụ bảng missing_df

               state  individuals  family_members   state_pop
region                                                       
Mountain     Arizona       7259.0             NaN         NaN
Mountain    Colorado          NaN          3250.0   5691287.0
Mountain       Idaho       1297.0           715.0   1750536.0
Pacific       Alaska       1434.0             NaN    735139.0
Pacific   California     109008.0         20964.0  39461588.0
Pacific       Hawaii       4131.0          2399.0         NaN

Để lọc dữ liệu chứa NaN ta dùng phương thức .dropna()

DataFrame.dropna(axis=0, how='any', thresh=None, subset=None, inplace=False)

Trong đó:

  • axis: Nhận diện lọc theo dòng 0, index, hay cột 1, column

  • how: Chỉ định cách lọc

    • any: Nếu có bất kì NA, loại bỏ dòng hoặc cột
    • all: Nếu tất cả là NA, loại bỏ dòng hoặc cột
  • thresh: Số lượng non-NA yêu cầu

  • subset: Chỉ định các cột cần lọc

  • inplace: Thực hiện trên chính DataFrame hay tạo bản sao.

Lọc bỏ các hàng nếu ít nhất một phần tử NA

missing_df.dropna(axis=0)
               state  individuals  family_members   state_pop
region                                                       
Mountain       Idaho       1297.0           715.0   1750536.0
Pacific   California     109008.0         20964.0  39461588.0

Lọc bỏ các cột nếu ít nhất một phần tử NA

missing_df.dropna(axis='columns')
               state
region              
Mountain     Arizona
Mountain    Colorado
Mountain       Idaho
Pacific       Alaska
Pacific   California
Pacific       Hawaii

Lọc bỏ các dòng nếu tất cả phần tử trong các cột ['family_members', 'state_pop']NA

missing_df.dropna(axis='index', how='all', subset=['family_members', 'state_pop'])
               state  individuals  family_members   state_pop
region                                                       
Mountain    Colorado          NaN          3250.0   5691287.0
Mountain       Idaho       1297.0           715.0   1750536.0
Pacific       Alaska       1434.0             NaN    735139.0
Pacific   California     109008.0         20964.0  39461588.0
Pacific       Hawaii       4131.0          2399.0         NaN

Giữ lại các dòng có ít nhất 3 phần tử non-NA

missing_df.dropna(thresh=3)
               state  individuals  family_members   state_pop
region                                                       
Mountain    Colorado          NaN          3250.0   5691287.0
Mountain       Idaho       1297.0           715.0   1750536.0
Pacific       Alaska       1434.0             NaN    735139.0
Pacific   California     109008.0         20964.0  39461588.0
Pacific       Hawaii       4131.0          2399.0         NaN