2015-06-03 9 views
7

Voglio creare nuove colonne dividendo un vettore in un frame di dati.Creazione di nuove colonne dividendo una variabile in molte variabili (in R)

Ho una tale cornice di dati:

YEAR Variable1 Variable2 
2009 000000 00000001 
2010 000000 00000001 
2011 000000 00000001 
2009 000000 00000002 
2010 000000 00000002 
2009 000000 00000003 
... 
2009 100000 10000001 
2010 100000 10000001 
... 
2009 100000 10000011 
.... 

Come si può vedere Variabile2 è legato a variabili 1 (Variabile2 = variabile1 + ultime due cifre: ad esempio 01, 02, 03 ... sottocategorie che indicano). Voglio dividere Variable2 in così tante variabili come sono le sottocategorie. Il risultato dovrebbe essere:

YEAR Variable1 Variable2 Variable3 Variable4 ... 
2009 000000 00000001 0   0   
2010 000000 00000001 0   0 
2011 000000 00000001 0   0 
2009 000000 0   00000002 0 
2010 000000 0   00000002 0 
2009 000000 0   0   00000003 
... 
2009 100000 10000001 0   0  
2010 100000 10000001 0   0  
... 
2009 100000 0   0   0  ...  10000011 

Come procedere? Ho pensato di provare a ricodificare Variable2 in un loop .. Ho provato a manipolare le stringhe, ma non ho risolto il problema ..

+0

quindi a seconda delle ultime due variabili si desidera creare una colonna e dare un valore quindi ci sarà un totale di circa 101 colonne è quello che si desidera – The6thSense

+1

Ad esempio al primo elemento in Variabile1 (000000) corrispondono 3 elementi in Variabile 2 (00000001, 00000002, 00000003) che dovrebbe essere riscritto in tre colonne diverse. Ogni volta che le ultime due cifre di un elemento in Variabile2 sono 01, quell'elemento rimane nella colonna della variabile due. Quando le ultime due cifre di un elemento in Variabile2 sono 02 quell'elemento va a Variabile3 (o se Variabile3 non esiste, viene creato). In questo modo vengono create nuove variabili solo se necessario. – woodstock

risposta

4

Questo funzionerà. Per prima cosa costruiamo i dati.

values <- paste0("0000000", 1:4) 
library(data.table) 
dt <- data.table(val = sample(values, 10, replace = TRUE)) 

Un ciclo for è sufficiente per definire le nuove colonne.

for(level_var in dt[, unique(val)]){ 
    dt[, eval(level_var) := ifelse(val == level_var, level_var, 0)] 
} 
+2

Buona risposta, eccetto che dovrai usare 'substr (eval (level_var), nchar (eval (level_var)) - 1, nchar (eval (level_var))): = ifelse (val == level_var, level_var, 0) dal momento che sembra che l'OP voglia che 'val = xxxxxxyy' sia la stessa nuova colonna per tutti i possibili prefissi di yy – Synergist

+0

C'è ancora un po 'di lavoro da fare l'OP vuole l'output come variabl1, variable2, ..... variable99 – The6thSense

+0

Capisco cosa intendi .. Che cos'è "level_var"? Ho cercato documentazione sul pacchetto "data.table" ma non ho trovato nulla a riguardo. Grazie per l'aiuto! Il codice non funziona ancora sui miei dati .. Ma ci sto lavorando – woodstock

0

Ecco un altro approccio.Si noti che ho scelto di fare le variabili subcat fittizie in variabili indicatore binario per ridurre la ridondanza:

ingresso:

data <- read.table(header=TRUE, text=' 
    year var1  var2 
    2009 000000 00000001 
    2010 000000 00000001 
    2009 000000 00000002 
    2010 000000 00000002 
    2009 000000 00000003 
    2009 100000 10000001 
    2009 100000 10000004 
    2010 100000 10000010     
', colClasses = c('character', 'character', 'character')) 

Semplificazione colonna var2:

subCat <- function(s) { 
    substr(s, nchar(s) - 1, nchar(s)) 
} 
data$var2 <- subCat(data$var2) 

Creazione di manichini:

Metodo 1:

t <- table(1:length(data$var2), data$var2) 
data <- cbind(data, as.data.frame.matrix(t)) 
data$var2 <- NULL 

uscita:

year var1 01 02 03 04 10 
1 2009 000000 1 0 0 0 0 
2 2010 000000 1 0 0 0 0 
3 2009 000000 0 1 0 0 0 
4 2010 000000 0 1 0 0 0 
5 2009 000000 0 0 1 0 0 
6 2009 100000 1 0 0 0 0 
7 2009 100000 0 0 0 1 0 
8 2010 100000 0 0 0 0 1 

========================== =================================

Metodo 2:

library(dummies) 
data$var2 <- subCat(data$var2) 
data3 <- cbind(data, dummy(data$var2)) 
data3$var2 = NULL 

uscita:

year var1 data01 data02 data03 data04 data10 
1 2009 000000  1  0  0  0  0 
2 2010 000000  1  0  0  0  0 
3 2009 000000  0  1  0  0  0 
4 2010 000000  0  1  0  0  0 
5 2009 000000  0  0  1  0  0 
6 2009 100000  1  0  0  0  0 
7 2009 100000  0  0  0  1  0 
8 2010 100000  0  0  0  0  1 

===================================== ======================

Metodo 3:

dummies <- sapply(unique(data$var2), function(x) as.numeric(data$var2 == x)) 
data <- cbind(data, dummies) 
data$var2 = NULL 

uscita:

year var1 X01 X02 X03 X04 X10 
1 2009 000000 1 0 0 0 0 
2 2010 000000 1 0 0 0 0 
3 2009 000000 0 1 0 0 0 
4 2010 000000 0 1 0 0 0 
5 2009 000000 0 0 1 0 0 
6 2009 100000 1 0 0 0 0 
7 2009 100000 0 0 0 1 0 
8 2010 100000 0 0 0 0 1 
0
library(dplyr) 
library(reshape2) 
df <- data.frame(YEAR=c(2009,2010,2011,2009,2010,2009,2009,2010,2009), 
         Var1=c('000000','000000','000000','000000','000000','000000','100000','100000','100000'), 
         Var2=c('0000001','0000001','0000001','0000002','0000002','0000003','1000001','1000001','1000011')) 

df <- mutate(df, tag=paste(YEAR, Var1, Var2, sep='-')) 
df <- dcast(df, YEAR + Var1 + tag ~ Var2, fun.aggregate = NULL) 
df$tag <- NULL 
df <- apply(df, 2, function(x) sub('^(.*)-(.*)-', '', x)) 
df[is.na(df)] <- 0 
df <- as.data.frame(df) 

uscita:

YEAR Var1 0000001 0000002 0000003 1000001 1000011 
1 2009 000000 0000001  0  0  0  0 
2 2009 000000  0 0000002  0  0  0 
3 2009 000000  0  0 0000003  0  0 
4 2009 100000  0  0  0 1000001  0 
5 2009 100000  0  0  0  0 1000011 
6 2010 000000 0000001  0  0  0  0 
7 2010 000000  0 0000002  0  0  0 
8 2010 100000  0  0  0 1000001  0 
9 2011 000000 0000001  0  0  0  0 
0

Grazie per tutte queste risposte. Ho trovato la soluzione combinando la risposta di Michele Usuelli e il commento alla sua risposta di Sinergista. Ho anche imparato di più su data.table

NbTabelle <- data.table(val=Netz) 
attach(NbTabelle) 
for(level_var in namesvec){ 
NbTabelle[, eval(level_var) := ifelse(substr(eval(val), 7, 8) == level_var, val, 0)] 
} 

Dove namesvec è il vettore nomi variabile che ho creato dalle tabelle generate precedenti, lasciando a parte la val variabile. Ho apprezzato la generalità del codice Synergist, ma per il mio scopo avevo bisogno solo delle ultime due cifre.

1

Utilizzo di reshape2. Una soluzione a una linea. Un'altra linea se vogliamo rimuovere i valori di NA.

library(reshape2) 
df <- data.frame(YEAR=c(2009,2010,2011,2009,2010,2009,2009,2010,2009), 
       Var1=c('000000','000000','000000','000000','000000','000000','100000','100000','100000'), 
       Var2=c('0000001','0000001','0000001','0000002','0000002','0000003','1000001','1000001','1000011')) 
df <- dcast(df, YEAR + Var1 + Var2 ~ Var2, value.var = "Var2")[, -3] 
df[is.na(df)] <- 0 

Risultato:

YEAR Var1 0000001 0000002 0000003 1000001 1000011 
1 2009 000000 0000001  0  0  0  0 
2 2009 000000  0 0000002  0  0  0 
3 2009 000000  0  0 0000003  0  0 
4 2009 100000  0  0  0 1000001  0 
5 2009 100000  0  0  0  0 1000011 
6 2010 000000 0000001  0  0  0  0 
7 2010 000000  0 0000002  0  0  0 
8 2010 100000  0  0  0 1000001  0 
9 2011 000000 0000001  0  0  0  0 
1

Ecco un altro suggerimento. Il codice è un po 'più lungo, ma credo che faccia il trucco, e spero che possa essere compreso facilmente. Suppongo che i dati originali siano memorizzati in un file separato da tab denominato 'data.dat'. L'output del codice è memorizzato nella matrice 'new_matrix'. Le voci sono caratteri, ma non dovrebbe essere un problema convertirli in numeri interi se necessario.

data <- read.table('data.dat', sep='\t', header = TRUE, colClasses = "character") 
var2 <- data[3] 
nc <- nchar(var2[1,1]) 
last2 <-substr(var2[,1],nc-1,nc) 
subcat <-levels(factor(last2)) 
mrows <- nrow(data) 
mcols <- length(subcat) 
varnames <-paste0("Variable",as.character(c(1:(mcols+1)))) 
new_matrix <- matrix(paste(replicate(nc,"0"),collapse=""),nrow=mrows,ncol=mcols+2) 
colnames(new_matrix) <- c("YEAR",varnames) 
new_matrix[,1]<-data[,1] 
new_matrix[,2]<-data[,2] 
for (i in 1:mcols) { 
    relevant_rows <- which(last2 == subcat[i]) 
    new_matrix[relevant_rows,i+2]<-data[relevant_rows,3] 
} 

Spero che questo aiuti.

Problemi correlati