Tự Học Data Science · 07/11/2023 0

03.01 Introducing Pandas Objects

Chuỗi đối tượng Pandas

Một Pandas Series là một mảng một chiều gồm dữ liệu được đánh chỉ mục.Nó có thể được tạo từ một danh sách hoặc mảng như sau:

data = pd.Series([0.25, 0.5, 0.75, 1.0])data
0    0.251    0.502    0.753    1.00dtype: float64

Nhìn vào kết quả, ta thấy Series bao gồm cả một chuỗi các giá trị và một chuỗi các chỉ số, mà chúng ta có thể truy cập bằng các thuộc tính valuesindex.Các values chỉ đơn giản là một mảng NumPy quen thuộc:

data.values
array([ 0.25,  0.5 ,  0.75,  1.  ])

Cái index là một đối tượng giống như một mảng của kiểu pd.Index, chúng ta sẽ thảo luận chi tiết hơn về nó sau.

data.index
RangeIndex(start=0, stop=4, step=1)

Tương tự như với một mảng NumPy, dữ liệu có thể được truy cập thông qua chỉ số liên quan bằng cú pháp dấu ngoặc vuông Python quen thuộc:

data[1]
0.5
data[1:3]
1    0.502    0.75dtype: float64

Như chúng ta sẽ thấy, Series của Pandas được coi là phổ biến và linh hoạt hơn rất nhiều so với mảng một chiều của NumPy mà nó mô phỏng.

Series như một mảng tổng quát hóa của NumPy

Cho đến thời điểm hiện tại, có vẻ như đối tượng Series có thể thay thế hoàn toàn mảng một chiều của NumPy.Sự khác biệt cơ bản là sự hiện diện của chỉ số: trong khi Mảng Numpy có một chỉ số nguyên được xác định một cách ngầm định để truy cập vào các giá trị, đối tượng Series của Pandas có một chỉ số được xác định rõ ràng liên kết với các giá trị.

Định nghĩa chỉ số rõ ràng này mang đến cho đối tượng Series các tính năng bổ sung. Ví dụ, chỉ số không nhất thiết phải là một số nguyên, mà có thể bao gồm các giá trị của bất kỳ loại nào mà chúng ta mong muốn.Ví dụ, nếu chúng ta muốn, chúng ta có thể sử dụng chuỗi làm chỉ số:

data = pd.Series([0.25, 0.5, 0.75, 1.0],                 index=['a', 'b', 'c', 'd'])data
a    0.25b    0.50c    0.75d    1.00dtype: float64

Và việc truy cập các mục hoạt động như dự kiến:

data['b']
0.5

Chúng ta có thể sử dụng cả các chỉ mục không liên tục hoặc không tuần tự:

data = pd.Series([0.25, 0.5, 0.75, 1.0],                 index=[2, 5, 3, 7])data
2    0.255    0.503    0.757    1.00dtype: float64
data[5]
0.5

Series như một từ điển chuyên ngành

Bằng cách này, bạn có thể coi một Series trong Pandas một chút giống như một từ điển Python chuyên biệt.Một từ điển là một cấu trúc mà phân ánh các khóa tùy ý tới một tập các giá trị tùy ý, và một Series là một cấu trúc mà ánh xạ các khóa có kiểu tới một tập các giá trị có kiểu.Kiểu này là quan trọng: giống như mã nguồn được biên dịch cụ thể cho một mảng NumPy giúp tăng hiệu suất so với một danh sách Python cho một số phép toán nhất định, thông tin kiểu dữ liệu của một Series Pandas giúp nó hiệu quả hơn rất nhiều so với từ điển Python cho một số phép toán nhất định.

Để giải thích một cách rõ ràng hơn về sự tương đương giữa Series và từ điển, chúng ta có thể tạo trực tiếp một đối tượng Series từ một từ điển Python:

population_dict = {'California': 38332521,                   'Texas': 26448193,                   'New York': 19651127,                   'Florida': 19552860,                   'Illinois': 12882135}population = pd.Series(population_dict)population
California    38332521Florida       19552860Illinois      12882135New York      19651127Texas         26448193dtype: int64

Mặc định, một Series sẽ được tạo ra, trong đó chỉ mục được lấy từ các khóa đã được sắp xếp.Từ đây, có thể thực hiện truy cập các mục theo kiểu từ điển thông thường:

population['California']
38332521

Khác với một từ điển, Series cũng hỗ trợ các hoạt động kiểu mảng như cắt:

population['California':'Illinois']
California    38332521Florida       19552860Illinois      12882135dtype: int64

Chúng ta sẽ thảo luận về một số điểm kỳ quặc của việc chỉ mục và cắt mảng trong Pandas trong Index và Lựa Chọn Dữ Liệu.

Xây dựng đối tượng Series

Chúng ta đã thấy một vài cách để xây dựng một Series trong Pandas từ đầu; tất cả các cách đó đều là một phiên bản của sau đây:

>>> pd.Series(data, index=index)

trong đó index là một đối số tùy chọn, và data có thể là một trong nhiều thực thể.

Ví dụ, data có thể là một danh sách hoặc một mảng NumPy, trong trường hợp này index mặc định là một chuỗi số nguyên:

pd.Series([2, 4, 6])
0    21    42    6dtype: int64

dữ liệu có thể là một số thuộc loại scalar, nó được lặp lại để điền vào chỉ số được chỉ định:

pd.Series(5, index=[100, 200, 300])
100    5200    5300    5dtype: int64

data có thể là một từ điển, trong đó index mặc định là các khóa của từ điển đã được sắp xếp:

pd.Series({2:'a', 1:'b', 3:'c'})
1    b2    a3    cdtype: object

Trong mỗi trường hợp, chỉ số có thể được thiết lập một cách rõ ràng nếu kết quả khác được ưa thích:

pd.Series({2:'a', 1:'b', 3:'c'}, index=[3, 2])
3    c2    adtype: object

Lưu ý rằng trong trường hợp này, Series chỉ được điền dữ liệu thông qua các khóa được xác định rõ ràng.

Đối tượng DataFrame trong Pandas

Cấu trúc cơ bản tiếp theo trong Pandas là DataFrame.Giống như đối tượng Series được thảo luận trong phần trước, DataFrame có thể được coi là một sự tổng quát hóa của một mảng NumPy hoặc là một sự đặc biệt hóa của từ điển Python.Bây giờ chúng ta sẽ xem xét từng quan điểm này.

DataFrame như một mảng NumPy tổng quát

Nếu một Series tương đương với một mảng một chiều với các chỉ mục linh hoạt, một DataFrame tương đương với một mảng hai chiều với cả chỉ mục hàng linh hoạt và tên cột linh hoạt.Giống như bạn có thể nghĩ về một mảng hai chiều là một chuỗi được sắp xếp của các cột một chiều, bạn có thể nghĩ về một DataFrame như một chuỗi của các đối tượng Series được sắp xếp.Ở đây, “được sắp xếp” có nghĩa là chúng có chia sẻ cùng một chỉ mục.

Để minh họa điều này, hãy trước tiên xây dựng một Series mới liệt kê diện tích của mỗi trong năm tiểu bang được thảo luận ở phần trước:

area_dict = {'California': 423967, 'Texas': 695662, 'New York': 141297,             'Florida': 170312, 'Illinois': 149995}area = pd.Series(area_dict)area
California    423967Florida       170312Illinois      149995New York      141297Texas         695662dtype: int64

Bây giờ chúng ta đã có điều này cùng với Series population từ trước đó, chúng ta có thể sử dụng một từ điển để xây dựng một đối tượng hai chiều duy nhất chứa thông tin này:

states = pd.DataFrame({'population': population,                       'area': area})states

Giống như đối tượng Series, DataFrame có một thuộc tính index để truy cập các nhãn chỉ mục:

states.index
Index(['California', 'Florida', 'Illinois', 'New York', 'Texas'], dtype='object')

Thêm vào đó, DataFrame có một thuộc tính là columns, đây là một đối tượng Index chứa các nhãn cột:

states.columns
Index(['area', 'population'], dtype='object')

Do đó, DataFrame có thể được coi là sự tổng quát hóa của một mảng NumPy hai chiều, trong đó cả hàng và cột đều có một chỉ mục tổng quát để truy cập vào dữ liệu.

Số chia lợi dụng bằng từ Điển đặc biệt

Tương tự, chúng ta cũng có thể coi DataFrame như một loại đặc biệt của từ điển.Trong khi từ điển ánh xạ một khóa tới một giá trị, DataFrame ánh xạ một tên cột tới một Series chứa dữ liệu cột.Ví dụ, yêu cầu thuộc tính 'area' sẽ trả về đối tượng Series chứa các diện tích mà chúng ta đã thấy trước đây:

states['area']
California    423967Florida       170312Illinois      149995New York      141297Texas         695662Name: area, dtype: int64

Lưu ý điểm nghẽn tiềm năng ở đây: trong một mảng NumPy hai chiều, data[0] sẽ trả về dòng đầu tiên. Đối với một DataFrame, data['col0'] sẽ trả về cột đầu tiên.Vì lý do này, có lẽ tốt hơn là coi DataFrame như những từ điển tổng quát hơn là những mảng tổng quát, mặc dù cả hai cách nhìn vào tình huống đều có ích.Chúng ta sẽ khám phá các phương pháp linh hoạt hơn để lập chỉ mục DataFrame trong Data Indexing and Selection.

Tạo đối tượng DataFrame

Một Bảng dữ liệu Pandas có thể được xây dựng theo nhiều cách khác nhau.Ở đây chúng ta sẽ cung cấp một số ví dụ.

Từ một đối tượng Series đơn lẻ

Một DataFrame là một tập hợp các đối tượng Series, và một DataFrame với một cột có thể được tạo từ một Series duy nhất:

pd.DataFrame(population, columns=['population'])

Từ một danh sách của các từ điển

Mọi danh sách từ điển có thể được chuyển thành một DataFrame.Chúng tôi sẽ sử dụng một biểu đạt danh sách đơn giản để tạo dữ liệu:

data = [{'a': i, 'b': 2 * i}        for i in range(3)]pd.DataFrame(data)

Ngay cả khi một số khóa trong từ điển bị thiếu, Pandas sẽ điền vào chúng bằng giá trị NaN (tức là “không phải là số”):

pd.DataFrame([{'a': 1, 'b': 2}, {'b': 3, 'c': 4}])

Từ một từ điển các đối tượng Series

Như chúng ta đã thấy trước đây, một DataFrame có thể được tạo từ một từ điển các đối tượng Series:

pd.DataFrame({'population': population,              'area': area})

Từ một mảng NumPy hai chiều

Cho một mảng hai chiều dữ liệu, chúng ta có thể tạo ra một DataFrame với bất kỳ tên cột và chỉ mục nào.

pd.DataFrame(np.random.rand(3, 2),             columns=['foo', 'bar'],             index=['a', 'b', 'c'])

Từ một mảng có cấu trúc NumPy

Chúng ta đã bàn về mảng có cấu trúc trong Dữ liệu có cấu trúc: Mảng có cấu trúc của NumPy.Một DataFrame trong Pandas hoạt động tương tự như một mảng có cấu trúc và có thể được tạo trực tiếp từ một mảng có cấu trúc:

A = np.zeros(3, dtype=[('A', 'i8'), ('B', 'f8')])A
array([(0, 0.0), (0, 0.0), (0, 0.0)],       dtype=[('A', '<i8'), ('B', '<f8')])
pd.DataFrame(A)

Đối tượng Chỉ số của Pandas

Chúng ta đã thấy ở đây cả đối tượng SeriesDataFrame đều chứa một chỉ số rõ ràng cho phép bạn tham chiếu và thay đổi dữ liệu.Đối tượng Index này là một cấu trúc thú vị trong chính nó, và nó có thể được coi như một mảng không thay đổi hoặc như một tập hợp có thứ tự (kỹ thuật là một multi-set, vì đối tượng Index có thể chứa các giá trị lặp lại).Những quan điểm đó có một số kết quả thú vị trong các phép toán có sẵn trên các đối tượng Index.Ví dụ đơn giản, hãy tạo một Index từ một danh sách số nguyên:

ind = pd.Index([2, 3, 5, 7, 11])ind
Int64Index([2, 3, 5, 7, 11], dtype='int64')

Index như một mảng không thay đổi

Các Index trong nhiều trường hợp hoạt động giống như một mảng. Ví dụ, chúng ta có thể sử dụng cú pháp truy cập thông thường của Python để lấy giá trị hoặc lát cắt:

ind[1]
3
ind[::2]
Int64Index([2, 5, 11], dtype='int64')

Đối tượng Index cũng có nhiều thuộc tính quen thuộc từ mảng NumPy:

print(ind.size, ind.shape, ind.ndim, ind.dtype)
5 (5,) 1 int64

Một khác biệt giữa các đối tượng Index và mảng NumPy là các chỉ số không thể thay đổi – tức là, chúng không thể được sửa đổi thông qua các phương pháp bình thường:

ind[1] = 0
---------------------------------------------------------------------------TypeError                                 Traceback (most recent call last)<ipython-input-34-40e631c82e8a> in <module>()----> 1 ind[1] = 0/Users/jakevdp/anaconda/lib/python3.5/site-packages/pandas/indexes/base.py in __setitem__(self, key, value)   1243    1244     def __setitem__(self, key, value):-> 1245         raise TypeError("Index does not support mutable operations")   1246    1247     def __getitem__(self, key):TypeError: Index does not support mutable operations

Khả năng không thay đổi này giúp việc chia sẻ các chỉ số giữa nhiều DataFrame và mảng trở nên an toàn hơn, mà không bị các tác động phụ từ việc sửa đổi không cố ý các chỉ số.

Chỉ mục như một tập hợp được sắp xếp

Đối tượng Pandas được thiết kế để cung cấp hỗ trợ cho các thao tác như kết hợp dữ liệu giữa các bộ dữ liệu, phụ thuộc vào nhiều khía cạnh của toán học tập hợp.Đối tượng Index tuân thủ nhiều quy ước được sử dụng bởi cấu trúc dữ liệu set tích hợp sẵn của Python, để ta có thể tính toán các phép hợp, giao, hiệu và các phép kết hợp khác một cách quen thuộc:

indA = pd.Index([1, 3, 5, 7, 9])indB = pd.Index([2, 3, 5, 7, 11])
indA & indB  # intersection
Int64Index([3, 5, 7], dtype='int64')
indA | indB  # union
Int64Index([1, 2, 3, 5, 7, 9, 11], dtype='int64')
indA ^ indB  # symmetric difference
Int64Index([1, 2, 9, 11], dtype='int64')

Các hoạt động này cũng có thể được truy cập qua các phương thức của đối tượng, ví dụ như indA.intersection(indB).