【Python】Udemyでデータサイエンスを学ぶ(2)Pandas

Pythonのデータサイエンスの基礎について、Udemyの以下リンクの学習教材で学んだ内容の内、Pandasについてまとめています。

【教育・学習】資格・学習
総合情報サイト「コレダ!」がお届けする教育・学習における資格・学習の総合情報サイトです。

Series

SeriesはNumpyのArrayのようなもの。

Numpy のArrayとPandasの違いは、Seriesにはindexが付く

import pandas as pd
from pandas import Series
obj = Series([3,6,9,12])
obj

>
0     3
1     6
2     9
3    12

値やインデックスを取り出す

obj.values

> array([ 3,  6,  9, 12])

obj.index

> RangeIndex(start=0, stop=4, step=1)

indexに文字列を当てる

以下は第二次世界大戦での各国の国ごとの死者数のデータを作成する例

ww2_cas = Series([87000000, 43000000, 30000000, 2100000, 400000], index=['USSR', 'Germany', 'China', 'Japan', 'USA'])
ww2_cas

>
USSR       87000000
Germany    43000000
China       3000000
Japan       2100000
USA          400000

条件式を使う

ww2_cas[ww2_cas>4000000]

>
USSR       87000000
Germany    43000000

これはどんな結果が返ってきているかというとTrue, Falseの結果が返ってきている。

ww2_cas>4000000

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

to_dict

Pythonの辞書型を作ることができる。

ww2_dict = ww2_cas.to_dict()
ww2_dict

>
{'USSR': 87000000,
 'Germany': 43000000,
 'China': 3000000,
 'Japan': 2100000,
 'USA': 400000}

辞書を基にSeriesを作ることもできる

ww2_Series = Series(ww2_dict)
ww2_Series

>
USSR       87000000
Germany    43000000
China       3000000
Japan       2100000
USA          400000

辞書を基にSeriesを作成する

countriesというindexを作成し、作成済みのSeriesであるww2_dictを基に新しいobj2というSeriesを作成する。

countries = ['China', 'Germany', 'Japan', 'USA', 'USSR', 'Argentina']
obj2 = Series(ww2_dict, index = countries)
obj2

>
China         3000000.0
Germany      43000000.0
Japan         2100000.0
USA            400000.0
USSR         87000000.0
Argentina           NaN

ww2_dictには無かったArgentinaはNaNとなる。

Series同士の足し算

indexが揃っていれば足し算してくれる。

ww2_Series + obj2
> 

Argentina            NaN
China          6000000.0
Germany       86000000.0
Japan          4200000.0
USA             800000.0
USSR         174000000.0

Seriesに名前を付ける

obj2.name = "第二次世界大戦の死者数"
obj2

>
China         3000000.0
Germany      43000000.0
Japan         2100000.0
USA            400000.0
USSR         87000000.0
Argentina           NaN
Name: 第二次世界大戦の死者数

indexにも名前を付けることができる。

obj2.index.name = 'Countries'
obj2

>
Countries
China         3000000.0
Germany      43000000.0
Japan         2100000.0
USA            400000.0
USSR         87000000.0
Argentina           NaN
Name: 第二次世界大戦の死者数

DataFrame

pandasのSeriesとDataFrameを使えるようにする。

import numpy as np
import pandas as pd
from pandas import Series, DataFrame

コピーしたデータの貼り付け

webブラウザ上でコピーした上で、以下を実行

mp_frame=pd.read_clipboard()
mp_frame

出力結果

カラムを取得

mp_frame.columns

>
Index(['順位', 'コード', '市場', '名称', '取引値', '発行済み株式数', '時価総額(百万円)', '単元株数', '掲示板'], dtype='object')

ちなみにコピー元サイトはこちら

株式ランキング(時価総額上位) - Yahoo!ファイナンス
株式投資に役立つ、国内上場銘柄を対象としたランキング。「値上がり」「値下がり」「出来高」など約40種類のランキング情報をデイリー、週次、月次や市場別で掲載。ストップ高や高値更新銘柄も。Yahoo!ファイナンスでは株価速報、チャート、ランキング、ポートフォリオ、ニュース、掲示板など投資判断に役立つ情報を掲載しています。

列の名前を取得

以下のようにカラム名で指定する

mp_frame['時価総額(百万円)']
>

1    34,905,916
2    17,862,898
3    17,669,038
4    13,303,110
5    12,872,604
6    12,102,027
7     9,212,559
Name: 時価総額(百万円)

複数列の取り出しの場合

mp_frame[['市場', '時価総額(百万円)']]

出力結果

(データコピー元のセルの関係でカラムがずれています。)

新しいDataFrameを作成する

上記は取得をしているのに対し、今回は新しくDataFrame を作成する。

出力結果としては同じ。

DataFrame(mp_frame, columns=['市場', '時価総額(百万円)'])

最初の数行を取り出す

5行を取り出す場合

mp_frame.head()

行数を指定する場合

引数を指定することができる。

mp_frame.head(3)

こうすると3行が取得できる。

最後からいくつかの数行を取り出す

headと同様に…

mp_frame.tail()

mp_frame.tail(3)

index を使ってデータにアクセスする

ixを使う。

mp_frame.ix[3]

新しい列を追加する

mp_frame['配当'] = "10円"

これで配当というカラムに全て10円が追加される。

列を削除する

頭にdelを付ける。

del mp_frame['コード']

これで、コードカラムの列が削除される。

DataFrameを辞書から作る

まずは、Pythonの辞書型をdataという名前で作成

city_frameという名前でDataFrameを作成

data = {'City':['SF', 'LA', 'NYC'], 'Population':[837000, 3880000, 8400000]}
data
>
{'City': ['SF', 'LA', 'NYC'], 'Population': [837000, 3880000, 8400000]}

city_frame = DataFrame(data)
city_frame

出力結果

indexの基本

簡単なSeriesを作成

おさらいになるが、Seriesは以下のように値とindexを指定して作成することができる。

import numpy as np
import pandas as pd
from pandas import Series, DataFrame
my_ser = Series([1,2,3,4], index=['A','B', 'C', 'D'])
my_ser

>
A    1
B    2
C    3
D    4

indexを取り出す

.indexで取り出せる。

my_index = my_ser.index
my_index

>
Index(['A', 'B', 'C', 'D'], dtype='object')

indexの中から要素を取り出す

my_index[0]

>
'A'

indexを変える

新たにrandnというものを使う。

import numpy as np
import pandas as pd
from pandas import Series, DataFrame
from numpy.random import randn

randnは正規分布に従った乱数を返すもの。

indexを書き換える

reindexを使い、indexを追加すると、indexが追加され、valueにはNaNが入る。

ser1 = Series([1,2,3,4], index = ['A', 'B', 'C', 'D'])
ser1
>
A    1
B    2
C    3
D    4

ser2 = ser1.reindex(['A', 'B', 'C', 'D', 'E', 'F'])
ser2
>
A    1.0
B    2.0
C    3.0
D    4.0
E    NaN
F    NaN

valueを指定する場合

ser2.reindex(['A', 'B', 'C', 'D', 'E', 'F', 'G'], fill_value=0)
>
A    1.0
B    2.0
C    3.0
D    4.0
E    NaN
F    NaN
G    0.0

行や列を削除する

import numpy as np
import pandas as pd
from pandas import Series, DataFrame

ser1 = Series(np.arange(3), index=['a', 'b', 'c'])
ser1
>
a    0
b    1
c    2

indexを指定して削除する

dropを使う。

ser1.drop('b')
>
a    0
c    2

これでbのindexを削除できる。

行の削除
dframe1 = DataFrame(np.arange(9).reshape((3,3)), index=['SF', 'LA', 'NY'], columns=['pop', 'size', 'year'])
dframe1

出力結果

これは基のDataFrameを削除したわけではなく、削除したDateFrameを表示しているに過ぎない。

列の削除

カラム名と、軸を指定する。

dframe1.drop('year', axis=1)

データを取り出す

import numpy as np
import pandas as pd
from pandas import Series, DataFrame
ser1 = Series(np.arange(3), index=['a', 'b', 'c'])
ser1 = 2* ser1
ser1
>
a    0
b    2
c    4

データにアクセスする

indexでもindex番号でもアクセスできる。

ser1['b']
>
2

ser1[1]
>
2

範囲の指定

ser1[0:3]

>
a    0
b    2
c    4

0から3の手間

文字列を使ったindex

同時に複数を指定できる。

ser1[['a','b']]
>
a    0
b    2

条件式を使う

3以上のみを出力

ser1[ser1>3]

3以上を10に置き換え

ser1[ser1>3] = 10
ser1
>
a     0
b     2
c    10

DaraFrameの場合

まずはDataFrameを作成

dframe = DataFrame(np.arange(25).reshape((5,5)), index=['NY','LA', 'SF', 'DC', 'Chi'], columns=['A', 'B', 'C', 'D', 'E'])

カラムを指定、条件付きで取得

行を取得

ixという行にアクセスできるメソッドは、2020年2月の1.0.0のバージョン更新で使えなくなり、文字列の場合はloc、index番号の場合はilocとなっている。

dframe.loc['LA']
>
A    5
B    6
C    7
D    8
E    9

dframe.iloc[1]
>
A    5
B    6
C    7
D    8
E    9

同じ結果が取得できる。

形の違うデータの計算

Series

形の違う2つのSeriesを用意し足し算する。

ser1 = Series([0,1,2], index=['A', 'B', 'C'])
ser1
>
A    0
B    1
C    2

ser2 = Series([3,4,5,6], index=['A', 'B', 'C', 'D'])
ser2
>
A    3
B    4
C    5
D    6

ser1 + ser2
>
A    3.0
B    5.0
C    7.0
D    NaN

結論:片方に無いindexはNaNとなる。

NaNとは

Not a Numberの略

DataFrame

2×2と3×3のDataFrameを作る。

dframe1 = DataFrame(np.arange(4).reshape((2,2)), columns=list('AB'), index=['NYC','LA'])
dframe2 = DataFrame(np.arange(9).reshape((3,3)), columns=list('ADC'), index=['NYC','SF', 'LA'])
dframe1 + dframe2

カラム名はこのようにlistで指定することができる。

出力結果

これらを足し合わせると、カラムが合っていないところはNaNとなる。

NaNになってしまうのを避ける方法

.addとすることで、存在する値の部分を埋めることができる。

dframe1.add(dframe2, fill_value=0)

DataFrameからSeriesを引く計算をする

DataFrameからSeriesを取り出し、

dframe2

dframe2 - ser3

行ごとに0, 1, 2が引かれる。

データの並び替えと順番

簡単なSeriesを作成

import numpy as np
import pandas as pd
from pandas import Series, DataFrame

ser1 = Series(range(3), index=['C', 'A', 'B'])
ser1

>
C    0
A    1
B    2

indexを使ってソート

ser1.sort_index()

>
A    1
B    2
C    0

値でのソート

orderを使う。

orderはバージョン変更により使えなくなった。

現在は、sort_values()

ser1.sort_values()

>
C    0
A    1
B    2

もう少しわかりやすいように、まずは乱数でSeriesを作成。

from numpy.random import randn
ser2 = Series(randn(10))
ser2

>
0   -1.090949
1   -0.576363
2    0.282948
3    0.804355
4   -0.284147
5    0.713147
6   -0.318596
7   -0.731993
8   -0.826768
9    1.504588

rank

並び替えたときに何番目になるか

ser2.rank()

>
0     1.0
1     4.0
2     7.0
3     9.0
4     6.0
5     8.0
6     5.0
7     3.0
8     2.0
9    10.0

データの統計量

まずはArrayを作成

import numpy as np
import pandas as pd
from pandas import Series, DataFrame
arr = np.array([[1,2,np.nan], [np.nan, 3,4]])
arr

>
array([[ 1.,  2., nan],
       [nan,  3.,  4.]])

ここで作ったArrayを基にDataFrameを作る。

dframe1 = DataFrame(arr, index=['A', 'B'], columns=['One', 'Two', 'Three'])

これにより名前を付与することができる。

列ごとの合計値を計算

dframe1.sum()

>
One      1.0
Two      5.0
Three    4.0

実はこの()は0の省略

行ごとの合計値を計算

dframe1.sum(axis=1)

>
A    3.0
B    7.0

列ごとの最小値/最大値

dframe1.min()

>
One      1.0
Two      2.0
Three    4.0

カラムの最小値がどの行か

idxminを使う。

dframe1.idxmin()

>
One      A
Two      A
Three    B

maxはminを変えるだけ!

累積計算

dframe1.cumsum()

TwoのBは2+3で5になっている。

まとまった情報を求める

dframe1.describe()

pandas.ioはバージョン変更により使用ができなくなり、
pandas_datareaderとなっている。

以下を実施したがエラー

import pandas_datareader 

そのため、以下を実施

pip install pandas_datareader

株価を取得するためにまずは2つimport

import pandas_datareader as pdweb
import datetime

3つのティッカーシンボルと、期間を指定して株価を取得

prices = pdweb.get_data_yahoo(['AAPL', 'GM', 'MSFT'],
                             start=datetime.datetime(2020,11,1),
                             end=datetime.datetime(2021,11,1))['Adj Close']
prices.head()

headにより先頭の5つを取得

変化の割合を計算

rets = prices.pct_change()
rets

描画をwebブラウザに埋め込む命令をする。

%matplotlib inline

すると、以下でブラフを出力することができる。

prices.plot()

相関係数を求める

corrを使う。

相関係数はグラフ化して求める事もできる。

重複データの取り除き、集計

値が重複しているSeriesを作る。

ser1 = Series(['w', 'w', 'x', 'y', 'w', 'x'])
ser1

>
0    w
1    w
2    x
3    y
4    w
5    x
unique

重複をまとめてくれる。

ser1.unique()

>
array(['w', 'x', 'y'], dtype=object)

value_counts

重複数を集計する。

ser1.value_counts()

>
w    3
x    2
y    1

欠損(Null)値の扱い

新たにnanというものを追加して、必要なものものをimportする。

import numpy as np
import pandas as pd
from pandas import Series, DataFrame
from numpy import nan

NaNを含んだSeriesを作成

data = Series(['one', 'two', nan, 'four'])
data

>
0     one
1     two
2     NaN
3    four

Nullかどうかの判断

data.isnull()

>
0    False
1    False
2     True
3    False

欠損値を取り除く

dropnaを使用

data.dropna()

>
0     one
1     two
3    four

NaNを含んだDataFrameを作成

dframe = DataFrame([[1,2,3], [nan,5,6], [7,nan,9],[nan,nan,nan]])
dframe

欠損値を取り除く

Null値がある行がすべて消える。

dframe.dropna()

全てが欠損値となっている行だけ消す

dframe.dropna(how='all')

列を削除する場合

dframe.dropna(axis=1)

axis1は列を意味しており、これでNullの列を削除できる。

欠損値で無い値の数をしきい値にする

threshを使う。

thresh=3とすると、欠損値で無い値が3個以上無い行は削除される。

欠損値を別のデータで埋める

fillnaを使う。

dframe2.fillna(1)

これで、欠損値NaNを1で埋めることができる。

埋める値を列ごとに指定する

dframe2.fillna({0:0, 1:1, 2:2, 3:3})

0列は0、1列は1となる。

indexの階層構造

randomパッケージから、randn関数もimport

import numpy as np
import pandas as pd
from pandas import Series, DataFrame
from numpy import nan

階層構造の確認

ser = Series(np.random.randn(6), index=[[1,1,1,2,2,2], ['a','b','c','a','b','c']])
ser

>
1  a    0.401007
   b   -1.178415
   c   -1.688628
2  a   -1.243104
   b   -0.238969
   c    0.821362

このように1や2を複数作ると、階層構造となる。

indexだけを表示してみると、、

ser.index

>
MultiIndex([(1, 'a'),
            (1, 'b'),
            (1, 'c'),
            (2, 'a'),
            (2, 'b'),
            (2, 'c')],
           )

Seriesを基にDataFrameを作る

dframe = ser.unstack()
dframe

逆にDataFrameからSeriesを呼ぶこともできる

dframe.unstack()

これだと列と行がひっくり返ってしまっているので、

dframe.T.unstack()

新たにDataFrameを作成

行のindexに名前を付ける

カラムに名前を付ける

カラムの階層を入れ替える

swaplevelを使い、横方向のaxis1を指定する。

行のソートをする

dframe2.sort_index(1)

引数の1はINDEX2の列をソートという意味

sortlevelはバージョン変更で使えなくなっている。

階層の計算

Tempの階層の合計値を求める。

コメント