45

再現可能なアプローチの例を提供するには、多くの場合、データセットを提供する必要があります。サンプルデータセットを作成する代わりに、自分のデータの一部を使用したいと思います。ただし、このデータは公開できません。変数(列)の名前と因子レベルを、情報のないプレースホルダー(V1 .... V5、L1 .... L5など)に置き換えたいと思います。

これを行う自動化された方法は利用できますか?

理想的には、これはRで行われ、data.frameを取り込んで、この匿名のdata.frameを生成します。

このようなデータセットを使用すると、スクリプト内の変数名を検索して置き換えるだけで、公開されている再現可能な例が得られます。

このようなプロセスにより、再現可能な例に適切なデータを含めることができ、質問、コメント、バグレポートに再現可能な例を含めることもできます。

4

3 に答える 3

40

これを自動化する機能があったかどうかはわかりませんが、はあります;)

## A function to anonymise columns in 'colIDs' 
##    colIDs can be either column names or integer indices
anonymiseColumns <- function(df, colIDs) {
    id <- if(is.character(colIDs)) match(colIDs, names(df)) else colIDs
    for(id in colIDs) {
        prefix <- sample(LETTERS, 1)
        suffix <- as.character(as.numeric(as.factor(df[[id]])))
        df[[id]] <- paste(prefix, suffix, sep="")
    }
    names(df)[id] <- paste("V", id, sep="")
    df
}

## A data.frame containing sensitive information
df <- data.frame(
    name = rep(readLines(file.path(R.home("doc"), "AUTHORS"))[9:13], each=2),
    hiscore = runif(10, 99, 100),
    passwd = replicate(10, paste(sample(c(LETTERS, letters), 9), collapse="")))

## Anonymise it
df2 <- anonymiseColumns(df, c(1,3))

## Check that it worked
> head(df, 3)
           name  hiscore    passwd
1 Douglas Bates 99.96714 ROELIAncz
2 Douglas Bates 99.07243 gDOLNMyVe
3 John Chambers 99.55322 xIVPHDuEW    

> head(df2, 3)
  name hiscore  V3
1   Q1 99.96714 V8
2   Q1 99.07243 V2
3   Q2 99.55322 V9
于 2012-05-04T20:24:23.577 に答える
16

これが私のバージョンの関数です。利点:forループがなく、レベルラベルが変数ラベルと一致し、任意のdfに適用でき、26文字を超える順序付けられた変数名、数値変数の正規化...


適用関数で列名を使用するための解決策を提供して
くれた@TylerRinkerと、この質問への回答を提供してくれた@JoshO'Brienに感謝します。

ここで要点として入手できます。

非因子変数を使用した@JoshO'Brienからのデータ

   df <- data.frame(
  name = rep(readLines(file.path(R.home("doc"), "AUTHORS"))[9:13], each=2),
  hiscore = runif(10, 99, 100),
  passwd = replicate(10, paste(sample(c(LETTERS, letters), 9), collapse="")))

df$passwd<-as.character(df$passwd)

関数

anonym<-function(df){
  if(length(df)>26){
    LETTERS<-replicate(floor(length(df)/26),{LETTERS<-c(LETTERS, paste(LETTERS, LETTERS, sep=""))})
    }
    names(df)<-paste(LETTERS[1:length(df)])

    level.id.df<-function(df){
        level.id<-function(i){
      if(class(df[,i])=="factor" | class(df[,i])=="character"){
        column<-paste(names(df)[i],as.numeric(as.factor(df[,i])), sep=".")}else if(is.numeric(df[,i])){
          column<-df[,i]/mean(df[,i], na.rm=T)}else{column<-df[,i]}
          return(column)}
      DF <- data.frame(sapply(seq_along(df), level.id))
      names(DF) <- names(df)
      return(DF)}
    df<-level.id.df(df)
    return(df)}

anonym(df)

結果:

    A                 B    C
1  A.1  1.00492190370171  C.8
2  A.1 0.997214883153158  C.2
3  A.2  1.00532434407094  C.5
4  A.2  1.00015775550051  C.6
5  A.3 0.998947207241593  C.3
6  A.3 0.998083738806433  C.4
7  A.5  1.00322085765279  C.7
8  A.5 0.995853096468764  C.1
9  A.4 0.998662338687036 C.10
10 A.4  0.99761387471706  C.9
于 2012-05-05T03:50:52.933 に答える
14

列名を匿名ラベルに置き換え、同様に要素のレベルを変更するだけの場合は、はい。最初に例として使用するいくつかのダミーデータ

dat <- data.frame(top_secret1 = rnorm(10), top_secret2 = runif(10),
                  top_secret3 = factor(sample(3, 10, replace = TRUE),
                                       labels = paste("Person", 1:3, sep = "")))

列名を置き換えるには、次のようにします。

dat2 <- dat
colnames(dat2) <- paste("Variable", seq_len(ncol(dat2)), sep = "")

これは

> head(dat2)
   Variable1 Variable2 Variable3
1 -0.4858656 0.4846700   Person3
2  0.2660125 0.1727989   Person1
3  0.1595297 0.6413984   Person2
4  1.1952239 0.1892749   Person3
5  0.3914285 0.6235119   Person2
6  0.3752015 0.7057372   Person3

次にレベルを変更します

foo <- function(x) {
    if(is.factor(x)) {
        levels(x) <- sample(LETTERS, length(levels(x)))
    }
    x
}
dat3 <- data.frame(lapply(dat2, foo))

これは

> head(dat3)
   Variable1 Variable2 Variable3
1 -0.4858656 0.4846700         K
2  0.2660125 0.1727989         G
3  0.1595297 0.6413984         O
4  1.1952239 0.1892749         K
5  0.3914285 0.6235119         O
6  0.3752015 0.7057372         K

foo()は、ベクトルを渡した関数の単純なラッパーであり、それが因子であるかどうかをチェックします。因子である場合は、レベルを適切な長さのランダムな文字のベクトルに変更してから、ベクトルを返します。

これを関数にラップして、要求されたすべての変更を行うことができます

anonymise <- function(df, colString = "Variable", rowString = "Sample") {
    foo <- function(x) {
        if(is.factor(x)) {
            levels(x) <- sample(LETTERS, length(levels(x)))
        }
        x
    }
    ## replace the variable names
    colnames(df) <- paste(colString, seq_len(ncol(df)), sep = "")
    ## fudge any factor levels
    df <- data.frame(lapply(df, foo))
    ## replace rownames
    rownames(df) <- paste(rowString, seq_len(nrow(df)), sep = "")
    ## return
    df
}

使用中、これは

> anonymise(dat)
           Variable1 Variable2 Variable3
Sample1  -0.48586557 0.4846700         F
Sample2   0.26601253 0.1727989         L
Sample3   0.15952973 0.6413984         N
Sample4   1.19522395 0.1892749         F
Sample5   0.39142851 0.6235119         N
Sample6   0.37520154 0.7057372         F
Sample7   1.18440762 0.7355211         F
Sample8   0.03605239 0.3924925         L
Sample9  -0.64078219 0.4579347         N
Sample10 -1.39680109 0.9047227         L
于 2012-05-04T20:30:04.953 に答える