¿Cómo crear un conjunto de datos de ejemplo a partir de datos privados(reemplazando nombres y niveles de variables con marcadores de lugar no informativos)?
(3)
Aquí está mi versión de la función. Ventajas: no hay bucles, etiquetas de nivel coinciden con etiquetas de variables, se pueden aplicar a cualquier df, nombres de variables ordenadas más allá de 26 letras, normalización de variables numéricas ...
Gracias ir a:
@Tyler Rinker para una solución al uso de nombres de columna en funciones de aplicación y
@Josh O''Brien por su respuesta a esta pregunta
Está disponible aquí como una esencia.
Los datos de @Josh O''Brien con una variable no factor
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)
La función
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)
Los resultados:
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
Para proporcionar un ejemplo reproducible de un enfoque, a menudo debe proporcionarse un conjunto de datos. En lugar de construir un conjunto de datos de ejemplo, deseo usar algunos de mis propios datos. Sin embargo, estos datos no pueden ser publicados. Deseo reemplazar los nombres variables (columna) y los niveles de los factores con marcadores de posición no informativos (por ejemplo, V1 .... V5, L1 .... L5).
¿Es una forma automatizada de hacer esto disponible?
Idealmente, esto se haría en R, tomando en un data.frame y produciendo este data.frame anónimo.
Con dicho conjunto de datos, simplemente busque y reemplace nombres de variables en su secuencia de comandos y tendrá un ejemplo reproducible públicamente liberable.
Tal proceso puede aumentar la inclusión de datos apropiados en ejemplos reproducibles e incluso la inclusión de ejemplos reproducibles en preguntas, comentarios e informes de errores.
No sé si había una función para automatizar esto, pero ahora lo hay;)
## 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
Si todo lo que quiere hacer es reemplazar los nombres de las columnas con etiquetas anónimas y también los niveles de factores, sí. Primero algunos datos ficticios para usar como ejemplo
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 = "")))
Para reemplazar los nombres de las columnas, haga lo siguiente:
dat2 <- dat
colnames(dat2) <- paste("Variable", seq_len(ncol(dat2)), sep = "")
Lo que da
> 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
Luego cambia los niveles
foo <- function(x) {
if(is.factor(x)) {
levels(x) <- sample(LETTERS, length(levels(x)))
}
x
}
dat3 <- data.frame(lapply(dat2, foo))
lo que da
> 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()
es simplemente un envoltorio simple para una función que pasa un vector comprueba si es un factor, si lo es, cambie los niveles a un vector de letras aleatorias de longitud apropiada, luego devuelva el vector.
Podemos ajustar esto en una función para hacer todos los cambios solicitados
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
}
En uso esto da
> 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