【データ解析の基本】 pandasでデータの加工をしよう

目次

pandasとは

pandasとは高性能で使いやすいデータ構造とデータ分析ツールを提供する非常に便利なPythonのライブラリです。

pandas

pandas: powerful Python data analysis toolk

今回は練習用データを構築して、pandasの様々な機能を一部紹介したいと思います。
また、練習用データの構築はスクレイピングで行います。
興味がある方は参考に勉強してみてください。

準備: 練習用データの構築 (ついでにスクレイピング)

pandasを扱うにあたって練習用のデータを構築します。

まずは必要モジュールをインポートします。
まだインストールされていない方は、pip install bs4のような感じでインストールしておいてください。

# スクレイピング用とデータ加工に必要なモジュール
from bs4 import BeautifulSoup
import csv
import requests

import pandas as pd
import numpy as np

pandasやnumpyはpdやnpとして使えるようにしていますが、何度も使うモジュールは省略してインポートするのが慣例です。
省略名は本来何でも良いのですが、上記のようにするのが一般的です。

あとは、練習用データをWebページから構築します。
もとにするサイトは2006年のテレビドラマの視聴率を掲載しているサイトです。
ここから番組ごとの視聴率がまとまっているテーブルのデータを抽出します。

Audience Rating TV ~ドラマ視聴率~

なお今回はpandasの機能を使うというのが本記事の目的なので、スクレイピングについてあまり説明しません。
興味がある方はこちらの記事をご参照ください。

【データ解析の基本】Webスクレイピング入門

# 2019/8/20の時点のWebページでは以下のようなコードでスクレイピングできます。
# ページのデザインが変わると機能しない場合がありますのでご了承ください。
url='https://artv.info/ar06-avg.html'
result = requests.get(url)
soup = BeautifulSoup(result.content)
summary = soup.find('table', class_='tableborder', id='simpleArTbl')
rows = summary.find_all('tr')

# データをCSVファイルとしてエクスポート
with open("AudienceRating2006.csv", "w", encoding='utf-8') as file:
    writer = csv.writer(file)
    for row in rows:
        csvRow = []
        for cell in row.findAll(['td', 'th']):
            csvRow.append(cell.get_text())
        writer.writerow(csvRow)

これで練習用データがカレントディレクトリにAudienceRating2006.csvとして保存できました。
このファイルをサンプルデータとして触りながら、pandasの機能を紹介します。

pandasの色々

pandasではDataFrameSeriesというデータ型を作成したり編集できます。
順番に見ていきます。

DataFrame

DataFrameとは簡単にいえばExcelのようなテーブル型のデータ形式です。
CSV形式の練習用のデータが作成できましたので、それを使ってDataFrameを色々触ってみましょう。

まずは先程作ったデータを読み込みます。
pandasには拡張子別でファイルを読み込むことができる便利なメソッドがあります。

ar_frame = pd.read_csv('AudienceRating2006.csv')
ar_frame
ar_frame

これでar_frameというDataFrameの形式に格納されています。
この形式だと様々なことが行えます。
head()やtail()というメソッドを使えば、上から5行もしくは下から5行読み込むことができます。
全部確認するにはデータ量が多すぎる場合には重宝します。

ar.frame.head()

例えば、データの列のタイトルを以下のように出力できます。

ar_frame.columns
Index(['年/月', '局', '時', 'タイトル', '1', '2', '3', '4', '5', '6', '7', '8', '9',
       '10', '11', '12', '平均'],
      dtype='object')

特定の行を抜き出すときは以下のようにできます。

ar_frame.loc[1]
year/month           '06/10
station                  CX
week/time               木22
title         Dr.コトー診療所2006
1                      23.2
2                      21.5
3                      21.6
4                      22.3
5                      21.9
6                      19.1
7                      21.1
8                      21.8
9                      22.0
10                     23.0
11                     25.9
12                        -
Ave                  22.35%
Name: 1, dtype: object

書き換えもrenameというメソッドを使って辞書型で指定することでできます。

ar_frame = ar_frame.rename(columns={'年/月': 'year/month', '局': 'station', '時': 'week/time', 'タイトル': 'title', '平均': 'Ave'})

基本的にcolumnのタイトルは英語で行ったほうが良いです。
英語の場合は定義したDataFrameのメソッドのようにデータを読み込むことができるからです。

ar_frame.title[:5]
0              西遊記
1    Dr.コトー診療所2006
2    マイ☆ボス マイ☆ヒーロー
3        のだめカンタービレ
4            14才の母
Name: title, dtype: object

Series

次にSeriesについて説明します。
Seriesは辞書型のような形式です。

obj = pd.Series([1,2,3,4])
obj
0    1
1    2
2    3
3    4
dtype: int64

indexと呼ばれる通し番号がSeriesを作成した際に特別していなければ自動で生成されます。
indexとそれに対応するvalueを呼び出すのも簡単です。

obj.values
array([1, 2, 3, 4])
obj.index
RangeIndex(start=0, stop=4, step=1)

それではもう少し込み入ったデータも作ってみましょう。
以下は第二次世界大戦での国別の死者を表すデータです。

ww2_cas = pd.Series([8700000,4300000,3000000,2100000,400000],index=['USSR','Germany','China','Japan','USA'])
ww2_cas
USSR       8700000
Germany    4300000
China      3000000
Japan      2100000
USA         400000
dtype: int64

indexを指定すれば特定のデータを抜き出せます。

ww2_cas['Japan']
2100000

条件をつけて抽出もできます。

ww2_cas[ww2_cas > 4000000]
USSR       8700000
Germany    4300000
dtype: int64

条件がTrueだけ抽出するという仕組みになっています。
ですので条件を入れると正誤を判定してくれます。

ww2_cas > 4000000
USSR        True
Germany     True
China      False
Japan      False
USA        False
dtype: bool

Seriesは辞書型に似ている先程説明しましたが、辞書型に変更することも可能です。

ww2_dict = ww2_cas.to_dict()
ww2_dict
{'USSR': 8700000,
 'Germany': 4300000,
 'China': 3000000,
 'Japan': 2100000,
 'USA': 400000}

また、辞書型からSeriesにもできます。

ww2_Series = pd.Series(ww2_dict)
ww2_Series
USSR       8700000
Germany    4300000
China      3000000
Japan      2100000
USA         400000
dtype: int64

indexは新たに追加できます。
追加したいindexをリストに入れておきます。

countries = ['China','Germany','Japan','USA','USSR','Argentina']
obj2 = pd.Series(ww2_dict, index=countries)
obj2
China        3000000.0
Germany      4300000.0
Japan        2100000.0
USA           400000.0
USSR         8700000.0
Argentina          NaN
dtype: float64

Argentinaはもともとデータが入っていません。
そのためデータが入っていないことを示すNaNとなっています。
このNaNを判定するisnullというメソッドもあります。

pd.isnull(obj2)
China        False
Germany      False
Japan        False
USA          False
USSR         False
Argentina     True
dtype: bool

Series同士は計算できます。
indexが共通していれば、計算してくれます。
Argentinaはデータが無いのでNaNのままです。

ww2_Series + obj2
Argentina           NaN
China         6000000.0
Germany       8600000.0
Japan         4200000.0
USA            800000.0
USSR         17400000.0
dtype: float64

indexやvalueに名前をつけることもできます。
日本語でもできますがエンコードの関係でPython2では対応していない等のことがあるので、基本的には英語でつけることをおすすめします。

ww2_cas.name = 'World War 2'
ww2_cas.index.name = 'Countries'
ww2_cas
Countries
USSR       8700000
Germany    4300000
China      3000000
Japan      2100000
USA         400000
Name: World War 2, dtype: int64

まとめ

今回はpandasの機能をDataFrameとSeriesという観点から紹介しました。
紹介できたのはほんの一部でpandasには他にも様々な便利機能が用意されています。

非常に重宝するライブラリなのでデータを触りながら少しずつ覚えていくと良いと思います。

本気でプログラミングを身につけるならCodeShip

CodeShipは業界内で唯一「無償延長保証制度」によるスキル修得を保証しているプログラミングスクールです。
独学での挫折や未経験からでも、スタートアップベンチャーや日系・外資の大手WEB系企業まで幅広くエンジニアを輩出する教育実績を残しています。

勉強目的ごとに用意された6つの学習コース現役エンジニアキャリアコンサルタントがあなたの「開発スキル修得」と「キャリアプランニング」をサポートします

さらに、期間内であれば選択した以外のコースのカリキュラムを受講可能。
同じ値段で、頑張った分だけ勉強できる「勉強し放題」はCodeShipだけ。

まずはご自身のプログラミング学習やキャリアプランについて、無料個別相談会にてお気軽にご相談ください。


おすすめ記事