Thứ năm, 23/02/2017 | 00:00 GMT+7

Phân tích và trực quan hóa dữ liệu với pandas và notebook Jupyter bằng Python 3

Gói pandas Python được sử dụng để thao tác và phân tích dữ liệu, được thiết kế để cho phép bạn làm việc với dữ liệu có nhãn hoặc dữ liệu quan hệ theo cách trực quan.

Gói pandas cung cấp chức năng bảng tính, nhưng vì bạn đang làm việc với Python nên nó nhanh hơn và hiệu quả hơn nhiều so với một chương trình bảng tính đồ họa truyền thống.

Trong hướng dẫn này, ta sẽ xem xét cài đặt một tập dữ liệu lớn để làm việc, các hàm groupby()pivot_table() của pandas và cuối cùng là cách trực quan hóa dữ liệu.

Để làm quen với gói pandas , bạn có thể đọc hướng dẫn của ta Giới thiệu về Gói pandas và Cấu trúc dữ liệu của nó trong Python 3 .

Yêu cầu

Hướng dẫn này sẽ trình bày cách làm việc với dữ liệu trong pandas trên máy tính local hoặc server từ xa. Làm việc với các tập dữ liệu lớn có thể tốn nhiều bộ nhớ, vì vậy trong cả hai trường hợp, máy tính cần ít nhất 2GB bộ nhớ để thực hiện một số phép tính trong hướng dẫn này.

Đối với hướng dẫn này, ta sẽ sử dụng Jupyter Notebook để làm việc với dữ liệu. Nếu bạn chưa có, bạn nên làm theo hướng dẫn của ta để cài đặt và cài đặt Jupyter Notebook cho Python 3 .

Cài đặt dữ liệu

Đối với hướng dẫn này, ta sẽ làm việc với dữ liệu An sinh xã hội của USA về tên trẻ em có sẵn từ trang web An sinh xã hội dưới dạng file zip 8MB.

Hãy kích hoạt môi trường lập trình Python 3 của ta trên máy local hoặc trên server của ta từ đúng folder :

  • cd environments
  • . my_env/bin/activate

Bây giờ ta hãy tạo một folder mới cho dự án của ta . Ta có thể gọi nó là names và sau đó chuyển vào folder :

  • mkdir names
  • cd names

Trong folder này, ta có thể kéo file zip từ trang web An sinh xã hội bằng lệnh curl :

  • curl -O https://www.ssa.gov/oact/babynames/names.zip

Khi file được download , hãy xác minh ta đã cài đặt tất cả các gói mà ta sẽ sử dụng:

  • numpy để hỗ trợ mảng đa chiều
  • matplotlib để trực quan hóa dữ liệu
  • pandas để phân tích dữ liệu của ta
  • seaborn để làm cho đồ họa thống kê matplotlib của ta trở nên thẩm mỹ hơn

Nếu bạn chưa cài đặt bất kỳ gói nào, hãy cài đặt chúng bằng pip , như trong:

  • pip install pandas
  • pip install matplotlib
  • pip install seaborn

Gói numpy cũng sẽ được cài đặt nếu bạn chưa có.

Bây giờ ta có thể khởi động Jupyter Notebook:

  • jupyter notebook

Khi bạn ở trên giao diện web của Jupyter Notebook, bạn sẽ thấy file names.zip ở đó.

Để tạo file sổ tay mới, hãy chọn Mới > Python 3 từ trình đơn kéo xuống trên cùng bên phải:

Tạo sổ ghi chép Python 3 mới

Thao tác này sẽ mở một sổ ghi chép.

Hãy bắt đầu bằng cách nhập các gói ta sẽ sử dụng. Ở đầu sổ ghi chép của ta , ta nên viết như sau:

import numpy as np import matplotlib.pyplot as pp import pandas as pd import seaborn 

Ta có thể chạy mã này và chuyển sang khối mã mới bằng lệnh ALT + ENTER .

Cũng hãy nói với Python Notebook để giữ cho đồ thị của ta nội tuyến:

matplotlib inline 

Hãy chạy mã và tiếp tục bằng lệnh ALT + ENTER .

Từ đây, ta sẽ chuyển sang extract repository zip, tải tập dữ liệu CSV vào pandas , sau đó nối các DataFrames pandas .

Extract repository Zip

Để extract file nén zip vào folder hiện tại, ta sẽ nhập module zipfile và sau đó gọi hàm ZipFile với tên của file (trong trường hợp của ta là names.zip ):

import zipfile zipfile.ZipFile('names.zip').extractall('.') 

Ta có thể chạy mã và tiếp tục bằng lệnh ALT + ENTER .

Bây giờ nếu bạn nhìn lại folder names của bạn , bạn sẽ có .txt của dữ liệu tên ở định dạng CSV. Các file này sẽ tương ứng với các năm dữ liệu trong file , 1881 đến 2015. Mỗi file này tuân theo một quy ước đặt tên tương tự. Ví dụ: file năm 2015 được gọi là yob2015.txt , trong khi file năm 1927 được gọi là yob1927.txt .

Để xem định dạng của một trong những file này, hãy sử dụng Python để mở một file và hiển thị 5 dòng trên cùng:

open('yob2015.txt','r').readlines()[:5] 

Chạy mã và tiếp tục với ALT + ENTER .

Output
['Emma,F,20355\n', 'Olivia,F,19553\n', 'Sophia,F,17327\n', 'Ava,F,16286\n', 'Isabella,F,15504\n']

Cách dữ liệu được định dạng là tên đầu tiên (như Emma hoặc Olivia ), giới tính tiếp theo (như F cho tên nữ và M cho tên nam), và sau đó là số trẻ sinh ra trong năm đó với tên đó (có 20.355 em bé tên là Emma sinh năm 2015).

Với thông tin này, ta có thể tải dữ liệu vào pandas .

Tải dữ liệu CSV vào pandas

Để tải dữ liệu giá trị được phân tách bằng dấu phẩy vào pandas ta sẽ sử dụng hàm pd.read_csv() , chuyển tên của file văn bản cũng như tên cột mà ta quyết định. Ta sẽ gán giá trị này cho một biến, trong trường hợp này là names2015 vì ta đang sử dụng dữ liệu từ file năm sinh 2015.

names2015 = pd.read_csv('yob2015.txt', names = ['Name', 'Sex', 'Babies']) 

ALT + ENTER để chạy mã và tiếp tục.

Để đảm bảo điều này hiệu quả, hãy hiển thị đầu bảng:

names2015.head() 

Khi ta chạy mã và tiếp tục với ALT + ENTER , ta sẽ thấy kết quả giống như sau:

 kết quả  tên2015.head

Bảng của ta bây giờ có thông tin về tên, giới tính và số trẻ sinh ra với mỗi tên được sắp xếp theo cột.

Nối các đối tượng pandas

Việc nối các đối tượng pandas sẽ cho phép ta làm việc với tất cả các file văn bản riêng biệt trong folder names .

Để nối các dữ liệu này, trước tiên ta cần khởi tạo một danh sách bằng cách gán một biến cho kiểu dữ liệu danh sách chưa được phổ biến:

all_years = [] 

Khi ta đã làm xong điều đó, ta sẽ sử dụng vòng lặp for để lặp lại tất cả các file theo năm, trong repository ảng từ 1880-2015. Ta sẽ thêm +1 vào cuối năm 2015 để năm 2015 được đưa vào vòng lặp.

all_years = []  for year in range(1880, 2015+1): 

Trong vòng lặp, ta sẽ thêm vào danh sách từng giá trị file văn bản, sử dụng trìnhđịnh dạng chuỗi để xử lý các tên khác nhau của từng file này. Ta sẽ chuyển các giá trị đó vào biến year . , ta sẽ chỉ định các cột cho Name , Sex và số lượng Babies :

all_years = []  for year in range(1880, 2015+1):     all_years.append(pd.read_csv('yob{}.txt'.format(year),                                  names = ['Name', 'Sex', 'Babies'])) 

Ngoài ra, ta sẽ tạo một cột cho mỗi năm để giữ những thứ đó có thứ tự. Điều này ta có thể làm sau mỗi lần lặp bằng cách sử dụng chỉ số -1 để trỏ đến chúng khi vòng lặp tiến triển.

all_years = []  for year in range(1880, 2015+1):     all_years.append(pd.read_csv('yob{}.txt'.format(year),                                  names = ['Name', 'Sex', 'Babies']))     all_years[-1]['Year'] = year 

Cuối cùng, ta sẽ thêm nó vào đối tượng pandas bằng cách ghép nối bằng cách sử dụng hàm pd.concat() . Ta sẽ sử dụng biến all_names để lưu trữ thông tin này.

all_years = []  for year in range(1880, 2015+1):     all_years.append(pd.read_csv('yob{}.txt'.format(year),                                  names = ['Name', 'Sex', 'Babies']))     all_years[-1]['Year'] = year  all_names = pd.concat(all_years) 

Bây giờ ta có thể chạy vòng lặp với ALT + ENTER , sau đó kiểm tra kết quả bằng cách gọi phần đuôi (các hàng dưới cùng) của bảng kết quả:

all_names.tail() 

all_names.tail outputl

Tập dữ liệu của ta hiện đã hoàn tất và sẵn sàng để thực hiện các công việc bổ sung với nó ở pandas .

Group dữ liệu

Với pandas bạn có thể group dữ liệu theo cột bằng hàm .groupby() . Sử dụng biến all_names cho tập dữ liệu đầy đủ của ta , ta có thể sử dụng groupby() để chia dữ liệu thành các group khác nhau.

Hãy group tập dữ liệu theo giới tính và năm. Ta có thể cài đặt điều này như vậy:

group_name = all_names.groupby(['Sex', 'Year']) 

Ta có thể chạy mã và tiếp tục với ALT + ENTER .

Đến đây, nếu ta chỉ gọi biến group_name ta sẽ nhận được kết quả này:

Output
<pandas.core.groupby.DataFrameGroupBy object at 0x1187b82e8>

Điều này cho ta thấy rằng nó là một đối tượng DataFrameGroupBy . Đối tượng này có hướng dẫn về cách group dữ liệu, nhưng nó không đưa ra hướng dẫn về cách hiển thị các giá trị.

Để hiển thị các giá trị, ta cần đưa ra hướng dẫn. Ví dụ, ta có thể tính toán .size() , .mean().sum() để trả về một bảng.

Hãy bắt đầu với .size() :

group_name.size() 

Khi ta chạy mã và tiếp tục với ALT + ENTER , kết quả của ta sẽ giống như sau:

Output
Sex Year F 1880 942 1881 938 1882 1028 1883 1054 1884 1172 ...

Dữ liệu này có vẻ tốt, nhưng nó có thể dễ đọc hơn. Ta có thể làm cho nó dễ đọc hơn bằng cách thêm hàm .unstack :

group_name.size().unstack() 

Bây giờ khi ta chạy mã và tiếp tục bằng lệnh ALT + ENTER , kết quả trông như sau :

 kết quả  group_name.size (). unack ()

Dữ liệu này cho ta biết có bao nhiêu tên nam và nữ mỗi năm. Ví dụ, vào năm 1889, có 1.479 tên nữ và 1.111 tên nam. Năm 2015 có 18.993 tên nữ và 13.959 tên nam. Điều này cho thấy có sự đa dạng hơn về tên gọi theo thời gian.

Nếu ta muốn lấy tổng số trẻ được sinh ra, ta có thể sử dụng hàm .sum() . Hãy áp dụng điều đó cho một tập dữ liệu nhỏ hơn, names2015 được đặt từ file yob2015.txt mà ta đã tạo trước đây:

names2015.groupby(['Sex']).sum() 

Hãy gõ ALT + ENTER để chạy mã và tiếp tục:

names2015.groupby (['Giới tính']). sum ()  kết quả

Điều này cho ta thấy tổng số trẻ sơ sinh nam và nữ được sinh ra trong năm 2015, mặc dù chỉ những trẻ được sử dụng tên ít nhất 5 lần trong năm đó mới được tính trong tập dữ liệu.

Hàm pandas .groupby() cho phép ta phân đoạn dữ liệu của bạn thành các group có ý nghĩa.

Bảng tổng hợp

Bảng tổng hợp rất hữu ích để tóm tắt dữ liệu. Chúng có thể tự động sắp xếp, đếm, tổng số hoặc dữ liệu trung bình được lưu trữ trong một bảng. Sau đó, họ có thể hiển thị kết quả của những hành động đó trong một bảng mới của dữ liệu tóm tắt đó.

pandas , hàm pivot_table() được sử dụng để tạo bảng tổng hợp.

Để tạo bảng tổng hợp, trước tiên ta sẽ gọi DataFrame mà ta muốn làm việc, sau đó là dữ liệu ta muốn hiển thị và cách chúng được group lại.

Trong ví dụ này, ta sẽ làm việc với dữ liệu all_names và hiển thị dữ liệu Trẻ sơ sinh được group theo Tên ở một thứ nguyên và Năm ở thứ khác:

pd.pivot_table(all_names, 'Babies', 'Name', 'Year') 

Khi ta gõ ALT + ENTER để chạy mã và tiếp tục, ta sẽ thấy kết quả sau:

 kết quả  pd.pivot_table (all_names, 'Babies', 'Name', 'Year')

Bởi vì điều này hiển thị nhiều giá trị trống, ta có thể cần giữ Tên và Năm dưới dạng cột thay vì dưới dạng hàng trong một trường hợp và các cột trong trường hợp khác. Ta có thể làm điều đó bằng cách group dữ liệu trong dấu ngoặc vuông:

pd.pivot_table(all_names, 'Babies', ['Name', 'Year']) 

Sau khi ta nhập ALT + ENTER để chạy mã và tiếp tục, bảng này giờ đây sẽ chỉ hiển thị dữ liệu cho các năm được ghi lại cho mỗi tên:

Output
Name Year Aaban 2007 5.0 2009 6.0 2010 9.0 2011 11.0 2012 11.0 2013 14.0 2014 16.0 2015 15.0 Aabha 2011 7.0 2012 5.0 2014 9.0 2015 7.0 Aabid 2003 5.0 Aabriella 2008 5.0 2014 5.0 2015 5.0

Ngoài ra, ta có thể group dữ liệu để có Tên và Giới tính làm một thứ nguyên và Năm thứ nguyên, như trong:

pd.pivot_table(all_names, 'Babies', ['Name', 'Sex'], 'Year') 

Khi ta chạy mã và tiếp tục với ALT + ENTER , ta sẽ thấy bảng sau:

pd.pivot_table (all_names, 'Babies', ["Name", "Sex"], "Year")

Bảng tổng hợp cho phép ta tạo bảng mới từ các bảng hiện có, cho phép ta quyết định cách ta muốn dữ liệu đó được group lại.

Trực quan hóa dữ liệu

Bằng cách sử dụng pandas với các gói khác như matplotlib ta có thể trực quan hóa dữ liệu trong sổ ghi chép của bạn .

Ta sẽ trực quan hóa dữ liệu về mức độ phổ biến của một tên cụ thể trong những năm qua. Để làm được điều đó, ta cần cài đặt và sắp xếp các index để làm lại dữ liệu cho phép ta thấy mức độ phổ biến thay đổi của một tên cụ thể.

Gói pandas cho phép ta thực hiện lập index phân cấp hoặc đa cấp, cho phép ta lưu trữ và thao tác dữ liệu với một số thứ nguyên tùy ý.

Ta sẽ lập index dữ liệu của bạn với thông tin về Giới tính, rồi Tên, rồi Năm. Ta cũng cần sắp xếp index :

all_names_index = all_names.set_index(['Sex','Name','Year']).sort_index() 

ALT + ENTER để chạy và tiếp tục đến dòng tiếp theo của ta , nơi ta sẽ có sổ ghi chép hiển thị DataFrame được lập index mới:

all_names_index 

Chạy mã và tiếp tục với ALT + ENTER , và kết quả sẽ giống như sau:

 kết quả  all_names_index

Tiếp theo, ta sẽ muốn viết một hàm sẽ vẽ biểu đồ mức độ phổ biến của một cái tên theo thời gian. Ta sẽ gọi hàm name_plot và chuyển sexname làm tham số của nó mà ta sẽ gọi khi chạy hàm.

def name_plot(sex, name): 

Bây giờ ta sẽ cài đặt một biến được gọi là data để giữ bảng ta đã tạo. Ta cũng sẽ sử dụng loc DataFrame của pandas để chọn hàng của ta theo giá trị của index . Trong trường hợp của ta , ta muốn loc dựa trên sự kết hợp của các trường trong MultiIndex, đề cập đến cả dữ liệu sexname .

Hãy viết cấu trúc này vào hàm của ta :

def name_plot(sex, name):     data = all_names_index.loc[sex, name] 

Cuối cùng, ta sẽ muốn vẽ các giá trị bằng matplotlib.pyplot mà ta đã nhập dưới dạng pp . Sau đó, ta sẽ vẽ biểu đồ các giá trị của dữ liệu giới tính và tên dựa trên chỉ số, theo mục đích của ta là năm.

def name_plot(sex, name):     data = all_names_index.loc[sex, name]      pp.plot(data.index, data.values) 

ALT + ENTER để chạy và chuyển sang ô tiếp theo. Bây giờ ta có thể gọi hàm với giới tính và tên mà ta chọn, chẳng hạn như F cho tên nữ với tên đã cho là Danica .

name_plot('F', 'Danica') 

Khi bạn gõ ALT + ENTER ngay bây giờ, bạn sẽ nhận được kết quả sau:

Danica Name Plot  kết quả

Lưu ý tùy thuộc vào hệ thống bạn đang sử dụng, bạn có thể có cảnh báo về sự thay thế phông chữ, nhưng dữ liệu vẫn sẽ vẽ đúng.

Nhìn vào hình dung, ta có thể thấy rằng cái tên nữ Danica đã có một sự nổi tiếng nhỏ vào khoảng năm 1990 và đạt đỉnh ngay trước năm 2010.

Hàm ta đã tạo được dùng để vẽ biểu đồ dữ liệu từ nhiều tên, để ta có thể xem xu hướng theo thời gian trên các tên khác nhau.

Hãy bắt đầu bằng cách làm cho cốt truyện của ta lớn hơn một chút:

pp.figure(figsize = (18, 8)) 

Tiếp theo, hãy tạo một danh sách với tất cả các tên mà ta muốn vẽ:

pp.figure(figsize = (18, 8))  names = ['Sammy', 'Jesse', 'Drew', 'Jamie'] 

Bây giờ, ta có thể lặp qua danh sách bằng vòng lặp for và vẽ dữ liệu cho từng tên. Đầu tiên, ta sẽ thử các tên trung lập về giới tính sau đây là tên nữ:

pp.figure(figsize = (18, 8))  names = ['Sammy', 'Jesse', 'Drew', 'Jamie']  for name in names:     name_plot('F', name) 

Để làm cho dữ liệu này dễ hiểu hơn, hãy bao gồm chú giải:

pp.figure(figsize = (18, 8))  names = ['Sammy', 'Jesse', 'Drew', 'Jamie']  for name in names:     name_plot('F', name)  pp.legend(names) 

Ta sẽ gõ ALT + ENTER để chạy mã và tiếp tục, sau đó ta sẽ nhận được kết quả sau:

Tên cốt truyện,  kết quả  tên nữ

Trong khi từng cái tên dần dần trở nên phổ biến với quyền là tên nữ, thì cái tên Jamie lại được yêu thích áp đảo với quyền là tên nữ trong những năm khoảng 1980.

Hãy vẽ các tên giống nhau nhưng lần này là tên nam:

pp.figure(figsize = (18, 8))  names = ['Sammy', 'Jesse', 'Drew', 'Jamie']  for name in names:     name_plot('M', name)  pp.legend(names) 

, gõ ALT + ENTER để chạy mã và tiếp tục. Biểu đồ sẽ như sau:

Tên cốt truyện,  kết quả  tên nam

Dữ liệu này cho thấy sự phổ biến hơn giữa các tên, với Jesse nói chung là lựa chọn phổ biến nhất và đặc biệt phổ biến trong những năm 1980 và 1990.

Từ đây, bạn có thể tiếp tục chơi với dữ liệu tên, tạo hình ảnh trực quan về các tên khác nhau và mức độ phổ biến của chúng, đồng thời tạo các tập lệnh khác để xem các dữ liệu khác nhau để hình dung.

Kết luận

Hướng dẫn này đã giới thiệu cho bạn các cách làm việc với tập dữ liệu lớn từ cài đặt dữ liệu, group dữ liệu với groupby()pivot_table() , lập index dữ liệu với MultiIndex và trực quan hóa dữ liệu pandas bằng gói matplotlib .

Nhiều tổ chức và cơ quan cung cấp tập dữ liệu mà bạn có thể làm việc cùng để tiếp tục tìm hiểu về pandas và trực quan hóa dữ liệu. Chính phủ USA cung cấp dữ liệu thông qua data.gov chẳng hạn.

Bạn có thể tìm hiểu thêm về cách trực quan hóa dữ liệu với matplotlib theo hướng dẫn của ta về Cách vẽ dữ liệu trong Python 3 Sử dụng matplotlibCách vẽ biểu đồ tần suất từ bằng matplotlib với Python 3 .


Tags:

Các tin liên quan

Cách vẽ biểu đồ tần suất từ bằng matplotlib với Python 3
2017-02-17
Cách cài đặt gói pandas và làm việc với cấu trúc dữ liệu trong Python 3
2017-02-10
Cách cài đặt gói pandas và làm việc với cấu trúc dữ liệu trong Python 3
2017-02-10
Cách cài đặt gói pandas và làm việc với cấu trúc dữ liệu trong Python 3
2017-02-10
Cách viết module trong Python 3
2017-02-03
Cách cài đặt Python 3 và thiết lập môi trường lập trình trên server Ubuntu 16.04
2017-02-01
Cách khai báo module trong Python 3
2017-02-01
Hiểu Tuples trong Python 3
2017-01-19
Cách tạo các vòng lặp trong Python 3
2017-01-12
Hiểu toàn bộ danh sách trong Python 3
2017-01-12