# Pandas
import numpy as np
import scipy as sp
import pandas as pd
from pandas import Series, DataFrame
import matplotlib.pyplot as plt
import matplotlib as mpl
import seaborn as sns
%matplotlib inline
%precision 3
# 階層型インデックス
# サンプルデータ生成
np.random.seed(0)
df = DataFrame(np.random.randint(0,10,9).reshape((3,3)),
index = [
['a', 'a', 'b'],
[1, 1, 2]
],
columns = [
['Hakodate','Sapporo','Hakodate'],
['Blue','Red','Red']
] )
df
# index に名前をつける
df.index.names=['index1','index2']
df
# columns に名前をつける
df.columns.names = ['column1','column2']
df
# columnsの絞り込み
df['Hakodate']
# index2 を軸にした集計
df.sum(level = 'index2', axis=0)
# column2 を軸にした集計
df.sum(level = 'column2', axis=1)
# index要素の削除
# indexキーが2つあり、どちらも共通の場合はdropの引数をタプルにする必要がある。
df.drop(("a",1))
# データの結合
data1 = {'id':[100,101,102,103],
'point':[10,11,12,13]}
data2 = {'id':[102,103,104,105],
'point':[55,66,77,88]}
df1 = pd.DataFrame(data1)
df2 = pd.DataFrame(data2)
print(df1)
print('=================')
print(df2)
# inner join : 共通のキーがある場合にキーで結合(共通項目のみで共通でないキーは捨てられる)
pd.merge(df1, df2, on = 'id')
# full join :とにかく全結合
pd.merge(df1, df2, how = 'outer')
# インデックスをキーとして結合することもできる
data1 = {'id':[100,101,102,103],
'point':[10,11,12,13]}
data2 = {'id':[102,103,104,105],
'point':[55,66,77,88],
'index_num':[0,1,2,3]}
df1 = pd.DataFrame(data1)
df2 = pd.DataFrame(data2)
print(df1)
print('=================')
print(df2)
# df1のインデックスとdf2のindex_num
df3 = pd.merge(df1, df2, left_index= True, right_on='index_num')
df3
# left join : 左側の
data1 = {'id':[100,101,102,103],
'point':[10,11,12,13]}
data2 = {'id':[102,103,104,105],
'point':[55,66,77,88],
'index_num':[0,1,2,3]}
df1 = pd.DataFrame(data1)
df2 = pd.DataFrame(data2)
print(df1)
print('=================')
print(df2)
pd.merge(df1, df2, how = 'left')
# 縦結合 concat ただただ縦に積み上げる
data1 = {'a':[1,2,3,4],
'b':[11,22,33,44]}
data2 = {'A':[5,6,7,8],
'B':[55,66,77,88]}
df1 = pd.DataFrame(data1)
df2 = pd.DataFrame(data2)
print(df1)
print('============')
print(df2)
print('# concatの引数dfはリストで投げる必要がある')
pd.concat([df1, df2])
# データの操作・変換
#サンプルデータ
data = {'value1':[1,2,3,4,5],
'value2':[1,2,3,4,5]}
index = [['a', 'a', 'b', 'b','c'],
[1, 1, 2, 3, 4]]
df = pd.DataFrame(data, index=index)
df.index.names=['index1','index2']
df
# ピボット操作:行列を入れ替える
df2 = df.stack()
print(type(df2))
pd.DataFrame(df2)
df2
# 重複データの除去
# 重複のあるサンプルデータを生成
data = {'value1':[1,2,3,4,5,6,3,3],
'value2':[1,2,3,0,0,0,3,3]}
df = pd.DataFrame(data)
df
# 重複データを判定する duplicated()メソド
df.duplicated()
# 重複データを削除する drop_duplicates()メソド
df.drop_duplicates()
# マッピング処理:エクセルのvlookup(検索)のような機能
map_data = {'c1':'cc1',
'c2':'cc2',}
map_data
# マッピング処理 :DataFrameのcity列に対応した新しいcity2という列を追加する
# 追加する前のサンプルデータを生成
df1_data ={'city':['c1','c1','c2','c3'],
'name':['A','B','C','D']}
df1 = pd.DataFrame(df1_data)
df1
# 対応表を作成
map_data = {'c1':'cc1',
'c2':'cc2',}
print(map_data)
# city列の中でc1に対しては新規city2列を生成しcc1というデータを与える
df1['city2'] = df1['city'].map(map_data)
df1
# 無名関数とmap関数の組み合わせ:列の一部を取り出す
print(df1)
print()
# df['city2']の頭2文字を取り出して新しい列を作る
df1['city2']
df1['new'] = df1['city2'].map(lambda x: str(x)[0:2])
print(df1)
lambda x: str(x)[0:2]
# ビン分割
# サンプルデータを生成する
data ={'year': [1955, 1990, 1989, 1992, 2015, 1980, 2009, 2005, 2019, 2020]}
df = pd.DataFrame(data)
# ビンを用意する
bins = [1980, 1990, 2000, 2010, 2020]
# ビン分割を実行
cut_data = pd.cut(df.year, bins)
print(cut_data)
"""
1990は[1980,1990]のクラスに入る
1980を超えて1990以下 という意味
なので1980はどのbinにも属さないのでNaNになる
"""
# right=Falseオブションで 1980以上,1990未満に変更できる
# ビン分割を実行
cut_data = pd.cut(df.year, bins, right=False)
print(cut_data)
# 集計できる
pd.value_counts(cut_data)
# 集計に名前をつけられる
group_names = ['1980s','1990s','2000s','2010s' ]
cut_data = pd.cut(df.year, bins, right=False, labels=group_names)
pd.value_counts(cut_data)
# 分割数を数字で指定できる
pd.cut(df.year, 4)
# 分位点で分割できる
cut_data = pd.qcut(df.year, 2)
print(cut_data)
print()
pd.value_counts(cut_data)
# ヒスとグラム
df.hist(bins=6)
# データの集約とグループ演算
# サンプルデータの生成 region付き
data = {'id': [100,101,102,103,104,106,108,110],
'city': ['tokyo', 'osaka', 'kyoto', 'hakodate', 'tokyo', 'tokyo', 'osaka', 'kyoto'],
'birth_year': [1990, 1989, 1992, 1997, 1982, 1991, 1988, 1990],
'name': ['hiroshi', 'akiko', 'yuki', 'satoru', 'steeve', 'mituru', 'aoi', 'tarou'],
'region': ['kanto', 'kansai', 'kansai', 'hokkaido', 'kanto', 'kanto', 'kansai', 'kansai']}
df1 = pd.DataFrame(data)
df1
# cityの値を集計する
df1.groupby('city').size()
# cityを軸にしてbirth_yearの平均値を求める
df1.groupby('city')['birth_year'].mean()
# regionとcityの2軸にしても計算可能
df1.groupby(['region', 'city'])['birth_year'].mean()
# このままテーブルとして使用したいとき as_index = False
df1.groupby(['region', 'city'], as_index=False)['birth_year'].mean()
# groupbyメソドでイテレータを使う
# regionごと 順番に取り出す
# groupはregionを取り出し subdfはそのregionの行を抽出する
for group, subdf in df1.groupby('region'):
print(group)
print(subdf)
print()
# 複数の計算をまとめて行う aggメソド
# サンプルデータ
data = pd.read_csv('student-mat.csv', sep=';')
data.head()
# 列に count, mean , max , minを適用する
functions = ['count', 'mean', 'max', 'min']
grouped_data = data.groupby(['sex', 'address'])
grouped_data['age', 'G1'].agg(functions)
# 欠損データ 異常値 の取り扱い
# サンプルデータの生成
np.random.seed(0)
df = pd.DataFrame(np.random.rand(10, 4))
df
# NAにする
from numpy import nan as NA
df.iloc[1,0] = NA
df.iloc[2:3, 2] = NA
df.iloc[5:, 3] = NA
df
# リストワイズ削除 dropna:NaN を取り除く
df.dropna()
# ペアワイズ削除 絶対に使いたい列を指定してから dropnaする
df[[0,1]].dropna()
# fillnaで埋める
df.fillna(0).head()
# 前の値で埋める ffill:フォワードフィル
df.fillna(method = 'ffill').head()
# 平均値で埋める
df.fillna(df.mean()).head()
# 時系列データの取り扱い
import pandas_datareader.data as pdr
start_date = '2001/1/2'
end_date = '2016/12/30'
df = pdr.DataReader('DEXJPUS', 'fred', start_date, end_date)
df.head()
# 特定の年月のデータを参照する
df['2016-04'].head()
# 月毎 M のデータで末尾 lastのデータを取り出す
# resampling 頻度変更の意 他: D Y
df.resample('M').last().head()
# 欠損がある場合 : 日毎 D
df.resample('D').last().head()
# 前日のデータで埋める ffill
df.resample('D').ffill().head()
# データを1日ずらして shift() 比率を計算する
df['ratio'] = df / df.shift(1)
df.head()
# 1日の差分を計算する diff
data['diff'] = data['DEXJPUS'].diff(1)
data.head()
#pct_changeを使っても比率は計算できる
df['pct_change'] = df['DEXJPUS'].pct_change(1)
df.head()
# 過去3日移動平均
df['mean_3'] = df['DEXJPUS'].rolling(3).mean()
df.head()
# 過去3日標準偏差 stdメソド
df['std_3'] = df['DEXJPUS'].rolling(3).std()
df.head()
# =============== Script End =================