【R】コンマを小数点記号に使っている場合の処理
ヨーロッパ言語圏に多いみたいですが、小数点をドット(ピリオド)ではなく、コンマ(カンマ)を用いて表現する地域があります。
今私はノルウェーのデータ扱ってるんですが、どうしても数量データを文字列として読み込むので原因を調べてみたら、これでした。
こういうデータは、コンマが既に使われているので、CSVファイルなどのセパレーションは、セミコロンを使います。
そういったデータをRでロードするときは、もともと入ってるbaseパッケージのbase::read.csv2や、readrパッケージのreadr::read_csv2を使うか、readr::read_delimで、delimを指定してやるとよいです。
たとえば
r - 金額以外 - 小数点記号としてカンマで数字を読み取る方法は?
しかし、自分でこの小数点問題を処理しないといけない壁に当たりました。
read_csv2を使うと、自動的に「","を"."として読み込んどいたぜ!」的なメッセージと共に、コンマを小数点として読み込んでくれるので数値として扱えるのですが、今回はstata形式で受け取ったデータをreadstata13::read.dta13で読み込んだため、どうしてもコンマを含んでる列を数値として読み込んでくれなかったのです。
さて、その対策ですが端的に言うと、文字列のままカンマをドットに置き換えた後に、数値に変換します。
たとえば、以下のようなベクトルがあるとします。中身は小数点一桁までの数字ですが、小数点がコンマ、しかも3桁区切りがドットという悪夢。Rはこれを文字列として認識しています。
v1 = c("970,3","3.140,5","4.478,3","1.772,8","424,0","190,8","3.778,7","4.287,1","1.930,8","3.250,4") mode(v1) # character
これは既に文字列として認識されているので、文字列の中をカンマをドットに、ドットを除去、という処理を行います。
文字列の処理にはgsubも使えますが、今回はstringiパッケージのstringi::str_replace_all_regexを使っています。
str_replace_all_regexをネストさせて、入れ子の中はドットを除去(何もなし、と置換)しています。"\\."の\\は正規表現でドットをエスケープさせるために使っています。入れ子の外は、ドット除去したオブジェクトをコンマとドットに置き換えるための処理をしています。それらの処理をas.numeric()で囲んで完了です。
v2 = as.numeric( stri_replace_all_regex( stri_replace_all_regex(v1,"\\.",""), # replace dots with nothing ",",".")) # replace comma with dots print(v2) mode(v2)
結果は
> print(v2) [1] 970.3 3140.5 4478.3 1772.8 424.0 190.8 3778.7 4287.1 1930.8 3250.4 > mode(v2) [1] "numeric"
と、通常の数値となっています。
もしデータなどを扱っている状態で、複数の列でこの問題が起きているなら、dplyr::mutate_atを使って
df2 = df1 %>% mutate_at(vars(var1,var2,var3), funs(as.numeric( stri_replace_all_regex( stri_replace_all_regex(., "\\.",""), ",", ".") ) ) )
という感じで処理するといいかと思います。