リスト内包表記
前書き
今回は、リスト内包表記について説明します。リスト内包表記をマスターすれば、コードがスッキリします。
内包表記の説明と種類
内包表記はあるイテラブルオブジェクトを利用して、別のイテラブルオブジェクトを作成するための記法のことです。内包表記には、リスト内包表記・辞書内包表記・セット内包表記があります。特に、リスト内包表記は頻出です。
リスト内包表記
リスト内包表記の基本構文は、次のようになります。
- [式 for 変数 in イテレータ]
リスト内包表記は、
- イテレータから1つずつ要素を取り出す
- 変数に代入する
- 式で評価
- リストに加える
という一連の流れを繰り返します。 この流れは、for文と同じです。
# sample.py l1 = [] for i in range(10): l1.append(i) print(l1) l2 = [i for i in range(10)] # iという変数に要素を代入している print(l2) l3 = [i*2 for i in range(10)] # 全ての要素を2倍している print(l3)
# 実行結果 [0, 1, 2, 3, 4, 5, 6, 7, 8, 9] [0, 1, 2, 3, 4, 5, 6, 7, 8, 9] [0, 2, 4, 6, 8, 10, 12, 14, 16, 18]
実行結果は、上記のようになります。リスト内包表記により簡単に数字の配列を作成できることがわかります。このように、リスト内包表記を用いれば大概のfor文を置き換えることができます。式と書かれているところで何かしらの計算をすることもできます。
if文を含むリスト内包表記
if文を含むリスト内包表記の基本構文は、次のようになります。
- [式 for 変数 in イテレータ if 条件]
if文を含むリスト内包表記は、
- イテレータから1つずつ要素を取り出す
- 変数に代入する
- 条件判定⇨真:4番・偽:1番
- 式で評価
- リストに加える
という一連の流れを繰り返します。
#sample.py l1 = [] for i in range(10): if i % 2 == 0: l1.append(i) print(l1) l2 = [i for i in range(10) if i % 2 == 0] print(l2) l3 = [i*2 for i in range(10) if i % 2 == 0] print(l3)
[0, 2, 4, 6, 8] [0, 2, 4, 6, 8] [0, 4, 8, 12, 16]
実行結果は、上記のようになります。条件判定されて、期待通りの結果になっていることがわかります。
if~elseを含むリスト内包表記
if~else文を含むリスト内包表記の基本構文は、次のようになります。
- [式A if 条件 else 式B for 変数 in イテレータ ]
if~elseの場合は、ifのみの場合と場所が違うので気をつけてください。 if~else文を含むリスト内包表記は、
- イテレータから1つずつ要素を取り出す
- 変数に代入する
- 条件判定⇨真:式A・偽:式Bで評価
- リストに加える
という一連の流れを繰り返します。
# sample.py l1 = [] for i in range(10): if i % 2 == 0: l1.append(i) else: l1.append(i+1) print(l1) l2 = [i if i % 2 == 0 else i+1 for i in range(10)] print(l2) l3 = [i*2 if i % 2 == 0 else (i+1)*2 for i in range(10)] print(l3)
# 実行結果 [0, 2, 2, 4, 4, 6, 6, 8, 8, 10] [0, 2, 2, 4, 4, 6, 6, 8, 8, 10] [0, 4, 4, 8, 8, 12, 12, 16, 16, 20]
実行結果は上記のようになります。全ての要素を偶数にすることができました。
様々なリスト内包表記
今回紹介したものを組み合わせることによりできる、様々なリスト内包表記の例をサンプルとして挙げておきます。
# sample.py # 2次元リストの作成 l1 = [] l2 = [] for i in range(3): l2 = [] for j in range(3): l2.append(j) l1.append(l2) print(l1) l3 = [[i for i in range(3)] for _ in range(3)] # 使わない要素には_を使うことが多い print(l3)
# 実行結果 [0, 1, 2], [0, 1, 2], [0, 1, 2]] [[0, 1, 2], [0, 1, 2], [0, 1, 2]]
# sample.py # 複数の条件(要素が正なら1、負なら-1、ゼロなら0)による演算 l = [1, -2, 0, -3, 3, 5, 0, -2] l1 = [] for i in l: if i > 0: l1.append(1) elif i < 0: l1.append(-1) else: l1.append(0) print(l1) l2 = [1 if i > 0 else -1 if i < 0 else 0 for i in l] print(l2)
# 実行結果 [1, -1, 0, -1, 1, 1, 0, -1] [1, -1, 0, -1, 1, 1, 0, -1]
このようにリスト内包表記で様々なことができます。
しかし、複雑になりすぎるリスト内包表記は使わない方が良いでしょう。
あとがき
お疲れさまでした。辞書内包表記とセット内包表記は次回説明します。基本的にはリスト内包表記と同じです。
pandas~ファイル編~
前書き
久しぶりの更新となりました。今回は、ファイル操作について説明します。
csvファイルで保存
pandasは、to_csv()を使うことにより、DataFrame型やSeries型をcsvファイルとして保存できます。
- pd.to_csv(file): file引数には、保存したい場所へのパスとファイル名を与えます。
# to_csv.py import pandas as pd df = pd.DataFrame([['一', '二', '三'], ['one', 'two', 'three'], ['eins', 'zwei', 'drei']], index=['日本語', '英語', 'ドイツ語'], columns=[1, 2, 3]) print(df) df.to_csv('number.csv') # 同じディレクトリにnumber.csvファイルが作成される
# 実行結果 1 2 3 日本語 一 二 三 英語 one two three ドイツ語 eins zwei drei
上記の実行結果より、csvファイルとしてデータが保存できたことがわかります。
to_csvのオプション
to_csvには、様々な引数があります。ここでは、よく使うものを紹介します。
引数 | 説明 |
---|---|
index | インデックスを保存するかを真偽値で指定。デフォルトはTrue。 |
header | 列名を保存するかを真偽値で指定。デフォルトはTrue。 |
csvファイルの読み込み
pandasでcsvファイルを読み込むには、read_csv()を使います。
# read_csv.py import pandas as pd df_1 = pd.read_csv('number.csv') print(df_1) df_2 = pd.read_csv('number.csv', index_col=0, header=0) # index_colとheaderを指定 print(df_2)
# 実行結果 # print(df_1) Unnamed: 0 1 2 3 0 日本語 一 二 三 1 英語 one two three 2 ドイツ語 eins zwei drei # print(df_2) 1 2 3 日本語 一 二 三 英語 one two three ドイツ語 eins zwei drei
また、他のcsvファイルを試したい場合は気象庁などからダウンロードして確認してみてください。
read_csvのオプション
read_csvは、様々な引数があります。ここでは、よく使うものを紹介します。
引数 | 説明 |
---|---|
sep | 各行をフィールドに分割するのに用いる文字列や正規表現。csvファイルなら必要ありません。例えば、tsvファイルなら'\t'を指定します。 |
header | 列名として使う行の番号。デフォルトは0。ヘッダがない場合はNoneを指定。 |
index_col | インデックスとして使う列の番号。デフォルトはNone |
skiprows | ファイルの先頭から無視する行数。デフォルトは0。 |
nrows | ファイルの先頭で読み込む行数。 |
encoding | Unicodeとして用いる文字コード。デフォルトは'utf-8'。 |
引数の補足説明をします。
例えば、skiprows=10・nrows=10とした場合は、先頭から10行飛ばしたところから10行分読み込まれます。
また、日本のサイトが提供するcsvファイルは、shift-jis形式が多いのでencodingを指定する必要があるかもしれません。上記の気象庁のサイトでは、encoding='shift-jis'と指定する必要があります。
あとがき
お疲れ様でした。これで pandasについての説明は、簡単にですが一通り終わりです。次回は、内包表記について説明します。
pandas~欠損値編~
まえがき
今回は、欠損値の処理について説明します。欠損値の処理は、最近流行りの機械学習においても非常に重要です。
pandasにおける欠損値
pandasにおける欠損値は型に依らず全てNaN(Not a Number)で表現されます。
また、Pythonの組み込み値であるNoneも欠損値として扱われます。
欠損値の確認
欠損値の確認は、isnull()とnotnull()を使います。
- isnull(): 欠損値があるかどうかを示す真偽値を持ったオブジェクトを返す(欠損値がTrue)
- notnull(): isnull()と反対の動作
import pandas as pd import numpy as np sr = pd.Series([1, 2, 3, np.nan, 8]) print(sr.isnull()) print(sr.notnull()) df = pd.DataFrame([[1., 2., 2.5, 4.5], [1., np.nan, np.nan, 5.], [2., 3., 3.5, np.nan]]) print(df.isnull()) print(df.notnull())
# 実行結果 # print(sr.isnull()) 0 False 1 False 2 False 3 True 4 False dtype: bool # print(df.notnull()) 0 True 1 True 2 True 3 False 4 True dtype: bool # print(df.isnull()) 0 1 2 3 0 False False False False 1 False True True False 2 False False False True # print(df.notnull()) 0 1 2 3 0 True True True True 1 True False False True 2 True True True False
欠損率
isnull()を応用することにより、カラム毎のの欠損率を計算できます。
import pandas as pd import numpy as np df = pd.DataFrame([[1., 2., 2.5, 4.5], [1., np.nan, np.nan, 5.], [2., 3., 3.5, np.nan], [3., np.nan, 5., 6.], [4., np.nan, np.nan, np.nan]]) print((df.isnull().sum() / len(df)) * 100)
# 実行結果 0 0.0 1 60.0 2 40.0 3 40.0 dtype: float64
欠損値を除外
欠損値の除外は、dropna()を使います。
欠損値のある軸が削除されます。
- dropna(axis): axisで指定した軸に欠損値があるかを調べ、抽出して除外する。
import pandas as pd import numpy as np df = pd.DataFrame([[1., 2., 2.5, 4.5], [1., np.nan, np.nan, 5.], [2., 3., 3.5, np.nan], [3., np.nan, 5., 6.], [4., np.nan, np.nan, np.nan]]) df_0 = df.dropna(axis=0) df_1 = df.dropna(axis=1) print(df_0) print(df_1)
# 実行結果 # print(df_0) 0 1 2 3 0 1.0 2.0 2.5 4.5 # print(df_1) 0 0 1.0 1 1.0 2 2.0 3 3.0 4 4.0
欠損値の穴埋め
欠損値の穴埋めは、fillna()を使います。
-fillna(value): 指定したvalueで穴埋めする。
import pandas as pd import numpy as np df = pd.DataFrame([[1., 2., 2.5, 4.5], [1., np.nan, np.nan, 5.], [2., 3., 3.5, np.nan], [3., np.nan, 5., 6.], [4., np.nan, np.nan, np.nan]]) df_0 = df.fillna(0) # 0で埋める df_mean = df.fillna(df.mean()) # 平均値で埋める df_median = df.fillna(df.median()) # 中央値で埋める print(df_0) print(df_mean) print(df_median)
# 実行結果 # print(df_0) 0 1 2 3 0 1.0 2.0 2.5 4.5 1 1.0 0.0 0.0 5.0 2 2.0 3.0 3.5 0.0 3 3.0 0.0 5.0 6.0 4 4.0 0.0 0.0 0.0 # print(df_mean) 0 1 2 3 0 1.0 2.0 2.500000 4.500000 1 1.0 2.5 3.666667 5.000000 2 2.0 3.0 3.500000 5.166667 3 3.0 2.5 5.000000 6.000000 4 4.0 2.5 3.666667 5.166667 # print(df_median) 0 1 2 3 0 1.0 2.0 2.5 4.5 1 1.0 2.5 3.5 5.0 2 2.0 3.0 3.5 5.0 3 3.0 2.5 5.0 6.0 4 4.0 2.5 3.5 5.0
あとがき
お疲れ様でした。今回は、欠損値の処理について簡単な説明しました。
pandas~要素編~
前書き
今回は、要素の一意性や頻度、存在の確認方法について説明します。
一意な要素
一意な要素を求めるメソッドは、以下のものです。
- Series.unique() : Series中の一意な要素を求める。返り値は、list。
- DataFrame.nunique() : DataFrameの中の一意な要素の個数を求める。返り値は、Series。
# sample.py import pandas as pd s = pd.Series([1, 2, 3, 5, 8, 2, 4, 5, 3, 4, 5, 1]) print(s.unique()) d = pd.DataFrame([[1, 'a'], [2, 'a'], [3, 'c'], [5, 'c'], [2, 'a'], [2, 'd'], [4, 'd'], [5, 'c'], [3, 'c'], [4, 'd'], [5, 'c'], [1, 'a']]) print(d.nunique()) print(d.nunique(axis=1)) print(d.iloc[:, 0].unique()) # 0列目(Series型)を取り出し、unique()を使用
# 実行結果 # s.unique() array([1, 2, 3, 5, 8, 4]) # d.nunique() 0 5 1 3 dtype: int64 # d.unique(axis=1) 0 2 1 2 2 2 3 2 4 2 5 2 6 2 7 2 8 2 9 2 10 2 11 2 dtype: int64 # d.iloc[:, 0].unique() array([1, 2, 3, 5, 4])
上記の実行結果になります。DataFrameのnunique()はあまり使われません。最後の例のように、DataFrameは、一意な要素を求めたいSeriesを取り出してからunique()を使うことが多いです。
要素の頻度
要素の頻度を求めるメソッドは、以下のものです。
- Series.value_counts() : Series中の要素の頻度を求める。返り値は、Series。
# sample.py import pandas as pd s = pd.Series([1, 2, 3, 5, 8, 2, 4, 5, 3, 4, 5, 1]) print(s.value_counts()) d = pd.DataFrame([[1, 'a'], [2, 'a'], [3, 'c'], [5, 'c'], [2, 'a'], [2, 'd'], [4, 'd'], [5, 'c'], [3, 'c'], [4, 'd'], [5, 'c'], [1, 'a']]) print(d.iloc[:, 0].value_counts()) # 0列目(Series型)を取り出し、value_counts()を使用
# 実行結果 # s.values_counts() 5 3 4 2 3 2 2 2 1 2 8 1 dtype: int64 # d.iloc[:, 0].value_counts() 5 3 2 3 4 2 3 2 1 2 Name: 0, dtype: int64
上記の実行結果になります。Series中の要素の頻度が求められていることがわかります。
DataFrameには、value_counts()をそのまま使えません。使用したい場合は、apply()を使用します。apply()は、発展的な内容なので説明しませんが、例を載せておきます。
# sample_option.py import pandas as pd d = pd.DataFrame([[1, 'a'], [2, 'a'], [3, 'c'], [5, 'c'], [2, 'a'], [2, 'd'], [4, 'd'], [5, 'c'], [3, 'c'], [4, 'd'], [5, 'c'], [1, 'a']]) print(d.apply(pd.value_counts))
# 実行結果 0 1 5 3.0 NaN 2 3.0 NaN 4 2.0 NaN 3 2.0 NaN 1 2.0 NaN c NaN 5.0 a NaN 4.0 d NaN 3.0
要素の存在
要素の存在を求めるメソッドは、以下のものです。
- Series.isin(elements) : elements中の要素がSeriesの中に存在するかを求める。返り値は、真偽値の Series。
- DataFrame.isin(elements) : elements中の要素がDataFrameの中に存在するかを求める。返り値は、真偽値のDataFrame。
import pandas as pd s = pd.Series([1, 2, 3, 5, 8, 2, 4, 5, 3, 4, 5, 1]) print(s.isin([1, 3, 5])) d = pd.DataFrame([[1, 'a'], [2, 'a'], [3, 'c'], [5, 'c'], [2, 'a'], [2, 'd'], [4, 'd'], [5, 'c'], [3, 'c'], [4, 'd'], [5, 'c'], [1, 'a']]) print(d.isin([1, 3, 5, 'b', 'd'])) print(d.isin({0:[1, 3, 5], 1:['b', 'd']}))
# 実行結果 # s.isin([1, 3, 5]) 0 True 1 False 2 True 3 True 4 False 5 False 6 False 7 True 8 True 9 False 10 True 11 True dtype: bool # d.isin([1, 3, 5, 'b', 'd']) 0 1 0 True False 1 False False 2 True False 3 True False 4 False False 5 False True 6 False True 7 True False 8 True False 9 False True 10 True False 11 True # d.isin({0:[1, 3, 5], 1:['b', 'd']}) 0 1 0 True False 1 False False 2 True False 3 True False 4 False False 5 False True 6 False True 7 True False 8 True False 9 False True 10 True False 11 True False
上記の実行結果になります。DataFrameは、引数にlistとかdictを与えることができます。isin()関数は、フィルタリングするのによく使います。例を載せておきます。
# sample_option import pandas as pd s = pd.Series([1, 2, 3, 5, 8, 2, 4, 5, 3, 4, 5, 1]) s_ = s[s.isin([1, 3, 5])] # 要素が1,3,5だけを取り出す print(s_)
# 実行結果 0 1 2 3 3 5 7 5 8 3 10 5 11 1 dtype: int64
あとがき
お疲れさまでした。次回は、欠損値の処理について説明します。
pandas~要約統計量編~
前書き
前回に引き続き、今回もpandasの説明をします。今回は、欠損値と要約統計量を求めるメソッドについて説明(紹介)します。
欠損値
まずは、サンプルをみましょう。
# sample.py import pandas as pd import numpy as np sdata = {'A': 80, 'B': 70, 'C': 60, 'D': 0} stage = ['S', 'A', 'B', 'C', 'D'] data = pd.Series(sdata, index=stage) print(data)
# 実行結果 S NaN # 欠損値 A 80.0 B 70.0 C 60.0 D 0.0 dtype: float64
実行結果は上記のようになります。この例の場合は、sdataの中に見つかった4つのデータ(A, B, C, D)は正しくインデックスと対応付けられています。'S'に対応するデータは、sdataに存在しないためNaN(not a number)となります。pandasは、NaNを欠損値またはNA値として扱います。対応するデータが存在しないときは、欠損値が自動的に補完されます。
要約統計量
pandasには、要約統計量を計算する様々なメソッドがあります。ここでは、重要なものをいくつか説明します。
# sample.py import pandas as pd import numpy as np # np.nanにより欠損値にすることができる data = pd.DataFrame([[1.0, 2.0], [np.nan, 4.0], [5.0, np.nan], [7.0, 8.0]], index=['one', 'two', 'three', 'four'], columns=['a', 'b']) print(data) print(data.describe()) # 複数の要約統計量を計算する print(data.sum()) # 行の合計値 print(data.sum(axis=1)) # 列の合計値 print(data.mean()) # 行の平均値 print(data.std()) # 行の標準偏差 print(data.count()) # 行の欠損値ではない要素の数
# 実行結果 # print(data) a b one 1.0 2.0 two NaN 4.0 three 5.0 NaN four 7.0 8.0 # print(data.describe()) a b count 3.000000 3.000000 mean 4.333333 4.666667 std 3.055050 3.055050 min 1.000000 2.000000 25% 3.000000 3.000000 50% 5.000000 4.000000 75% 6.000000 6.000000 max 7.000000 8.000000 # print(data.sum()) a 13.0 b 14.0 dtype: float64 # print(data.sum(axis=1)) one 3.0 two 4.0 three 5.0 four 15.0 dtype: float64 # print(data.mean()) a 4.333333 b 4.666667 dtype: float64 # print(data.std()) a 3.05505 b 3.05505 dtype: float64 # print(data.count()) a 3 b 3 dtype: int64
実行結果は上記のようになります。describe()は複数の要約統計量を計算します。sum()・mean()・std()は合計値、平均値、標準偏差を計算します。また、axis=1のように指定することにより、計算対象の軸を変更できます。count()は欠損値以外の要素の個数を計算します。
よく使う要約統計量の一覧は以下になります。
メソッド | 意味 |
---|---|
describe | 複数の要約統計量を求める |
count | NA値ではない要素の個数を求める |
min, max | 最小値・最大値を求める |
argmin, argmax | 最小値・最大値が得られた場所のインデックスを求める |
sum | 合計値を求める |
mean | 平均値を求める |
median | 中央値を求める |
var | 分散を求める |
std | 標準偏差を求める |
cumsum | 累積和を求める |
また、上記のメソッドにおいてdescribe以外はaxisにより計算軸を指定することができます。axis=0が行・axis=1が列です。デフォルトではaxis=0となっています。そのほかにも、指定できるオプションはありますが、使用頻度は高くないので説明しません。
あとがき
お疲れさまでした。今回は、欠損値と要約統計量を求めるメソッドについて説明しました。次回は、欠損値の処理について説明したいと思います。