ともにゃん的データ分析ブログ

勉強したことの備忘録とかね

Pythonのpandasで大きなデータを扱うときにメモリ効率を上げる方法メモ

最近Pythonを使って大きなデータフレームを結合したり、そのデータフレームに対してメソッドを使って処理をしていますが、頻繁に

"Memory Error"

に遭遇しています。そんな中で色々探し回って見つけたTips的なものをメモとして残しておきます。

  • pandas.DataFrame.merge をする時に copy=False のオプションをつける

そもそもこのcopyってなんだかよくわからないのですが、使用メモリの挙動を見ている限りは copy=True とするとデータフレームを結合するときにそのcopyを用意して、それを参照している感じがします。copy=Falseで劇的にメモリ効率が良くなった気がします。

ちなみにpandas.DataFrame.mergeよりもpandas.DataFrame.joinの方が結合の効率が良いという報告もあります
参照:
python - Improve Pandas Merge performance - Stack Overflow

  • del 変数名 で変数を消して gc.collect() でメモリを開放

参照:
Pythonで少なくメモリを使用する方法 - のんびりしているエンジニアの日記

  • メソッドを呼び出すときは inplace=True オプションをつける

参照:
pandas でメモリに乗らない 大容量ファイルを上手に扱う - StatsFragments


特に中間テーブルなどを結合した最終的な結果データフレームだけを使いたい時などは、途中過程で生成されるデータフレームは結局使用されないと思うので、上記のオプションをつけても問題無いと思います。そうでなくても問題ないのかもしれません。

pandasのDataFrameのplotメソッドを使って描画するときにプロットを並べて表示する方法

pandasのDataFrameのplotメソッドを使って描画するときに、プロットを並べて表示する方法のメモ

import matplotlib.pyplot as plt
import pandas as pd

fig, axes = plt.subplots(nrows=1, ncols=2, squeeze=False)

df1.plot(kind="bar", x="x", y="y", ax=axes[0,0], figsize=(15, 5))
df2.plot(kind="bar", x="x", y="y", ax=axes[0,1], figsize=(15, 5))

XGBoostの概要

XGBoostの凄さに最近気がついたので、もうちょっと詳しく知りたいと思って以下の論文を読みました。

XGBoost: A Scalable Tree Boosting System

せっかくなので、簡単にまとめてみたいと思います。。。と思っていたら結構な量になってしいました。
何か間違い等がありましたらコメントをしていただくか、@kefism へ連絡をしてくださると嬉しいです。

続きを読む

tree系のアルゴリズム(決定木・ランダムフォレスト・xgboostなど)で目的変数に対数を取ってはいけない

よくよく考えたら当たり前のことに気づいたのでメモです。


回帰とかをするときに、例えば目的変数が正の値しか取り得ないような場合、目的変数を対数変換したりします。
そのノリで、タイトルに挙げたのtree系のアルゴリズムを適用するときにも対数変換をしてる人がいるんじゃないでしょうか。僕もその一人です。
ただ、どうも予測値が実測値を過小評価している感がすごかったのです。そこで原因を考えてみました。

続きを読む

【R】データフレームにcharacterやfactorの列が含まれているときに、その列をすべてダミー変数化する関数

タイトル通りの関数を作りましたのでここに置いておきます。
データフレームに文字列が入ってて分析を回せない、、、その列だけ取り出してダミー化してまた結合してって面倒くせえ、、、ってときにお使いください。

{dummies}パッケージを使用していますのでご注意ください。

is.dropは、多重共線性等を気にしたときにTRUEとしてください。1列抜かれます。

convOnlyCharacters2Dummies <- function(data, is.drop = FALSE){
  library(dummies)
  convDummies <- function(data, is.drop){
    N <- ncol(data)
    row_names <- names(data)
    
    names_list <- c()
    new_data <- rep(NA, nrow(data))
    for(n in 1:N){
      unique_value <- sort(unique(data[,n]))
      dummied_data <- dummy(data[,n])
      
      if(is.drop == TRUE){
        new_data <- cbind(new_data, dummied_data[,-ncol(dummied_data)])
        names_list <- c(names_list, 
                        paste(row_names[n], unique_value, sep = ".")[-ncol(dummied_data)])
      } else {
        new_data <- cbind(new_data, dummied_data)
        names_list <- c(names_list, paste(row_names[n], unique_value, sep = "."))
      }
    }
    
    new_data <- as.data.frame(new_data)
    names(new_data) <- c("temp", names_list)
    
    return(new_data[,-1])
  }
  
  varnames <- names(data)
  todummiesnames <- c()
  for(name in varnames){
    if(class(data[[name]]) == "character" || class(data[[name]]) == "factor"){
      todummiesnames <- c(todummiesnames, name)
    } 
  }
  dummies_df <- convDummies(data[, todummiesnames], is.drop)
  df <- cbind(data[, which(!(varnames %in% todummiesnames))], dummies_df)
  
  return(df)
}