読者です 読者をやめる 読者になる 読者になる

一所懸命に手抜きする

監査の仕事をしています。ITを利用し、良い意味で「手抜き」することは効率化と精度アップに役立つと思うんです。部下への引き継ぎのためにまずは諸々頭から引っ張り出そうとブログを始めました。

[ Main ]  [ 別館 ]
当ブログで取り上げられている事案やデータベース、人物等はすべてフィクションです。

列名の違いに関係なく列順で縦結合するユーザー関数(rbind拡張1)~三つ以上のデータフレーム対応

R

列名が違う場合には縦結合は困難

 各所に散在するデータベースを合体させて利用することがあります。
 同じ内容でもファイル名がバラバラ、ヘッダ名がバラバラということがよくあります。

項目順は同じでも項目名が違うことがある

▼Aさんの作った「社員台帳」

社員番号 部署 氏名
1 営業部 山田太郎
2 営業部 鈴木花子

▼Bさんが使っている「社員マスタ」

社員番号 所属 名前
3 総務部 杉本一郎
4 財務部 支払益子

▼Cさんが使っている「社員マスタ」

社員コード 所属 氏名
5 経理部 会計主水
6 秘書室 白鳥麗子

そんな時、rbind()ではエラー

 これらの例は本質的には同一フォーマットなので結合すればより多くの社員を網羅する社員台帳ができるはずです。これは縦結合と呼ばれる行為です。
 R では縦結合するための関数として rbind() が用意されています。

 まず、rbind()の動作を確認するために上の例に合わせたサンプルデータフレームを作成します。

テスト用にデータフレームを作成する R コード

# rbindM() テスト用のデータフレーム作成
社員台帳=data.frame(社員番号=c(1,2),部署=c("営業部","営業部"),氏名=c("山田太郎","鈴木花子")) 社員台帳
 社員番号 部署  氏名
1    1 営業部 山田太郎
2    2 営業部 鈴木花子
社員マスタ=data.frame(社員番号=c(3,4),所属=c("総務部","財務部"),名前=c("杉本一郎","支払益子")) 社員マスタ
社員番号  所属 名前
1   3 総務部 杉本一郎
2   4 財務部 支払益子
社員マスタ2=data.frame(社員番号=c(5,6),所属=c("経理部","秘書室"),名前=c("会計主水","白鳥麗子")) \> 社員マスタ2
社員番号 所属  名前
1   5 経理部 会計主水
2   6 秘書室 白鳥麗子

 用意した 社員台帳 と 社員マスタ に rbind() を実行してみます。

> rbind(社員台帳,社員マスタ)
以下にエラー match.names(clabs, names(xi)) : 名前が以前の名 前と一致しません

このようにエラー(列名が異なる!)が発生します。
標準の rbind() では 列名や列順が異なると縦結合できません。
ではどうすれば良いのでしょうか。

列名が違う場合に縦結合可能とする方法(1)~項目順は同じ~

 この例では列名が違っても内容の同じ列が同じ順番に並んでいることがポイントです。
 列名があるから「列名が異なる」と言われるのですから、列名をなくしてしまえば良いのでは。

ユーザー関数rbindCOrder()で解決する

 その発想で作成したユーザー関数 rbindCOrder() を実行してみます。

[R]ユーザー関数 rbindCOrder()実行例

> rbindCOrder(社員台帳,社員マスタ, 社員マスタ2)
 社員番号 部署  氏名
1    1 営業部 山田太郎
2    2 営業部 鈴木花子
3    3 総務部 杉本一郎
4    4 財務部 支払益子
5    5 経理部 会計主水
6    6 秘書室 白鳥麗子

縦結合できました。 今回作成した rbindCOrder() では

  • 列名の違いを無視するためNAに置き換えます。
  • 列順で縦結合します。
  • 第一引数のデータフレームから列名を採用します。
[R]ユーザー関数 rbindCOrder()
#----------------------------------------------------------#
#  rbindCOorder(df1,df2,df3…)
# 列名無視して順序で結合。三つ以上のデータフレームにも対応
# df1の列名を採用する。
# a b c
# a c d
# ↓
# a b c
# a c d
#----------------------------------------------------------#
rbindCOrder <- function(...)  {
        n <- length(list(...))
        temp <- list(...)[[1]]
            names(temp)<-NA
        for (i in 2:n) {
            tmp<-list(...)[[i]]
            names(tmp)<-NA
            temp <- rbind(temp, tmp)
        }
            names(temp)<-names(list(...)[[1]])
        return(temp)
    }
#----------------------------------------------------------#
  1. 列名が違うから縦結合ができない」わけですから、
  2. 列名をすべてNAで「揃えて」しまいます。
  3. そして標準のrbind()で縦結合を必要回数行い、
  4. データフレーム1の列名を結合データフレームの列名とします。
  5. 戻り値のデータ型などについてはご自由に変えてください。
  6. 列数が異なる場合にはエラーとなりますがエラー処理していません。
    ご使用は自己責任でお願いします。

a-habakiri.hateblo.jp

a-habakiri.hateblo.jp

広告を非表示にする