pandas

【Pandas】単位を削除して数値に変換する【Python】

MAX

データクレンジングをしていると、「10分」「100円」「$10.5」などの単位がついているデータに出会うことが割とよくある。

単位は非常に重要な情報だが、数値計算したい時には完全に不要になる。

整数や小数ぐらいなら、割と簡単だが、負数やマイナス記号と数字の間にスペースなどが入ってきたりすると、少しずつ面倒になってくる。

本記事ではextractで正規表現を使った抽出をメインに使う。

スポンサーリンク

単位を削除して数値(整数)に変換する

1import pandas as pd
2
3df = pd.DataFrame({
4    "time": ["1分", "10分", "30分", "60分"]
5})
6print(df)
7#   time
8# 0   1分
9# 1  10分
10# 2  30分
11# 3  60分
12
13# \d+で数字が1回以上出現するパターンを抽出する
14df["minutes"] = df["time"].str.extract('(\d+)').astype(int)
15print(df)
16#   time  minutes
17# 0   1分        1
18# 1  10分       10
19# 2  30分       30
20# 3  60分       60

こういったデータであれば、割と簡単だが、int型が簡単に通用するのは欠損値がない場合のみ。

単位を削除して数値(小数)に変換する

1import pandas as pd
2
3df = pd.DataFrame({
4    "price": ["$ 1.1", "$ 10.5", "$ 10"]
5})
6print(df)
7#     price
8# 0   $ 1.1
9# 1  $ 10.5
10# 2    $ 10
11
12# \d+は整数部分の数字。\.?は小数点がある場合に抽出。\d*は小数部分がある場合に抽出
13df["price_float"] = df["price"].str.extract('(\d+\.?\d*)').astype(float)
14print(df)
15#     price  price_float
16# 0   $ 1.1          1.1
17# 1  $ 10.5         10.5
18# 2    $ 10         10.0

正規表現に小数点を取得する処理(\.?)と小数点以下の数字を取得する処理(\d*)を追加している。

astypeでfloatに変換しているので、この場合は欠損値があってもOK。

データに欠損値が含まれる場合の処理

int型に変換する場合

int型に変換したい場合、欠損値があるとValueErrorとなるため、欠損値補間をしてからintに変換することになる。

欠損値はNaNとなるが、NaNはfloat型なのでintにはできない。

1import pandas as pd
2
3df = pd.DataFrame({
4    "time": ["1分", "10分", "", "60分"]
5})
6print(df)
7#   time
8# 0   1分
9# 1  10分
10# 2     
11# 3  60分
12
13# 欠損値がある場合NaNになるが、これはfloat型のため、intにしようとするとエラーとなる
14df["minutes"] = df["time"].str.extract('(\d+)').astype(int)
15# ValueError: cannot convert float NaN to integer

欠損値をfillna()などで適当な整数で埋めてからintに変換する。

1df["minutes"] = df["time"].str.extract('(\d+)').fillna("0").astype(int)
2print(df)
3#   time  minutes
4# 0   1分        1
5# 1  10分       10
6# 2             0
7# 3  60分       60

上記の例では0で補完しているが、対象データ内で欠損値として適切な値で整数であれば何でもいい。

float型に変換する場合

float型に変換する場合、欠損値があってもNaNとして扱えるので、特に何か対応する必要はない。

1import pandas as pd
2
3df = pd.DataFrame({
4    "price": ["$ 1.1", "$ 10.5", ""]
5})
6print(df)
7#     price
8# 0   $ 1.1
9# 1  $ 10.5
10# 2    
11
12# floatにする場合、欠損値はNaNになる
13df["price_float"] = df["price"].str.extract('(\d+\.?\d*)').astype(float)
14print(df)
15#     price  price_float
16# 0   $ 1.1          1.1
17# 1  $ 10.5         10.5
18# 2                  NaN

負数が含まれるデータの単位削除

基本的には正規表現でマイナス記号も抽出するように修正する。

数字の直前にマイナス記号がある場合

正規表現に-?を追加するだけで抽出可能。

1import pandas as pd
2
3df = pd.DataFrame({
4    "price": ["1.1円", "10.5円", "10円", "-10.0円", ""]
5})
6print(df)
7#     price
8# 0    1.1円
9# 1   10.5円
10# 2     10円
11# 3  -10.0円
12# 4        
13
14# -?でマイナスが0回か1回含まれるパターンを抽出
15df["price_float"] = df["price"].str.extract('(-?\d+\.?\d*)').astype(float)
16print(df)
17#     price  price_float
18# 0    1.1円          1.1
19# 1   10.5円         10.5
20# 2     10円         10.0
21# 3  -10.0円        -10.0
22# 4                  NaN

この例ではマイナス記号のすぐ後に数字がある場合パターンのため、抽出したパターンはそのまま数値に変換できる。

しかし、抽出したパターンをそのまま数値に変換できない場合、extractで抽出してからreplaceなどで数字に変換できない部分を置換するなどが必要になる。

数字とマイナス記号の間に空白がある場合

スペースが含まれていると、そのままではfloatに変換できないので、スペースを削除する必要がある。

1import pandas as pd
2
3df = pd.DataFrame({
4    "price": ["1.1円", "10.5円", "10円", "-10.0円", "- 10円"]
5})
6print(df)
7#     price
8# 0    1.1円
9# 1   10.5円
10# 2     10円
11# 3  -10.0円
12# 4  - 10 円 
13
14# \s*でスペースが0回以上ある場合に対応。
15# extractはDataFrameを返すため、列0に対してreplaceでスペースを削除する
16# replaceでスペースを削除せずにfloatにしようとするとエラーとなる
17df["price_float"] = df["price"].str.extract('(-?\s*\d+\.?\d*)')[0].str.replace(" ", "").astype(float)
18print(df)
19#     price  price_float
20# 0    1.1円          1.1
21# 1   10.5円         10.5
22# 2     10円         10.0
23# 3  -10.0円        -10.0
24# 4   - 10円        -10.0

extractで抽出した結果はDataFrameとして返ってくる。この時、列名は0, 1, …のようになる。

今回の場合、1列のみを対象としているので、extractで返ってくるDataFrameの列は0のみになる。

extractで返ってきた列に対してreplaceでスペースを削除する。

その後、floatに変換できる。

まとめ

1# -N.NNなどの数値を抽出
2df["price_float"] = df["price"].str.extract('(-?\d+\.?\d*)').astype(float)
3
4# - N.NNなどの数値を抽出
5df["price_float"] = df["price"].str.extract('(-?\s*\d+\.?\d*)')[0].str.replace(" ", "").astype(float)
6

スポンサーリンク
ABOUT ME
MAX
MAX
ITエンジニア、データサイエンティスト
新卒でSIerに入社し、フリーランスになってWEB系へ転向。
その後AIの世界へ足を踏み入れ、正社員に戻る。 テーブルデータの分析がメイン。
スポンサーリンク
記事URLをコピーしました