2017-05-02 8 views
1

Kurz gesagt, möchte ich den umgekehrten Prozess von model.matrix() machen. Ich habe die folgenden Daten aus einer Umfrage erhalten.R - Mehrere Zeichenspalten finden und kombinieren

Frage 1: eine von 'Cat' holen, 'Dog' oder 'Sheep'
Frage 2: Wählen Sie eine Zufallszahl
Frage 3:

Der aus 'Big' oder 'Small' wählen Ergebnisse werden in einem Datenrahmen in der folgenden Art und Weise setzen:

id ans_1 ans_2 ans_3 num size_1 size_2 
    1 Cat  0  0  0.76 0  Small 
    2 0  Dog  0  0.44 0  Small 
    3 0  0  Sheep 0.52 Big  0  
    4 0  0  Sheep 0.52 Big  0  
    5 0  Dog  0  0.59 0  Small 
    6 Cat  0  0  0.97 0  Small 
    7 0  Dog  0  0.5 0  Small 
    8 0  Dog  0  0.19 0  Small 
    9 0  0  Sheep 0.01 Big  0  
    10 Cat  0  0  0.24 0  Small 

Was ich die Antworten jeder Frage, in einer einzigen Spalte tun will zu kombinieren ist. In diesem Beispiel stammen ans_1, ans_2 und ans_3 aus derselben Frage und Größe_1 und Größe_2. Kombiniert sie, würden die Ergebnisse wie aussehen:

id ans  num size 
    1 Cat  0.76 Small   
    2 Dog  0.44 Small   
    3 Sheep 0.52 Big   
    4 Sheep 0.52 Big   
    5 Dog  0.59 Small   
    6 Cat  0.97 Small   
    7 Dog  0.5 Small   
    8 Dog  0.19 Small  
    9 Sheep 0.01 Big   
    10 Cat  0.24 Small   

Ich habe mehrere Datensätze, von denen jeder etwa 100 Spalten enthält. Dies macht es zu viel Arbeit von Hand zu tun. Beachten Sie, dass es auch Spalten wie "num" gibt, die für sich stehen. Die Antworten auf die gleiche Frage sind immer gleich nebeneinander wie in diesem Beispiel.

Vielen Dank!

Daten

id = 1:10 
ans_1 = c('Cat', 0, 0, 0, 0, 'Cat', 0, 0, 0, 'Cat') 
ans_2 = c(0, 'Dog', 0, 0, 'Dog', 0, 'Dog', 'Dog', 0, 0) 
ans_3 = c(0, 0, 'Sheep', 'Sheep', 0, 0, 0, 0, 'Sheep', 0) 
num = round(runif(10),2) 
size_1 = c(0, 0, 'Big', 'Big', 0, 0, 0, 0, 'Big', 0) 
size_2 = c('Small', 'Small', 0, 0, 'Small', 'Small', 'Small', 'Small', 0, 
'Small') 

data <- noquote(cbind(id, ans_1, ans_2, ans_3, num, size_1, size_2)) 
+0

'cbind' kehrt eine Matrix, keine Daten .Rahmen. Verwenden Sie einfach "data.frame". – alistaire

+0

Eine Option, um es zu bereinigen: 'Bibliothek (Tidyverse); Daten%>% unclass()%>% as_data_frame()%>% muate_all (na_if, '0')%>% type_convert()%>% muate (ans = coalesce (ans_1, ans_2, ans_3), size = coalesce (size_1, size_2))%>% select (-matches ('_ \\ d + $')) ' – alistaire

Antwort

0

Sie können dies mit Matrix erreichen subsetting und max.col wie diese. 4 und dann unter Verwendung von Matrix subsetting zurückzukehren Elemente in jeder Reihe, die den gewünschten Ausgang entsprechen:

dataNew <- data.frame(id=data$id, 
        ans=data[,2:4][cbind(seq_along(data$id), max.col(data[, 2:4] != "0"))], 
        num=data$num, 
        size=data[,6:7][cbind(seq_along(data$id), max.col(data[, 6:7] != "0"))], 
        stringsAsFactors=FALSE) 

Die dritte Variable, num wird durch subsetting auf Variablen 2 angelegt. In diesem Fall seq_along gibt den Satz von Zeilen und max.col verwendet wird, innerhalb jeder Zeile die Variable zu finden, die nicht 0

Daten

data <- 
structure(list(id = 1:10, ans_1 = c("Cat", "0", "0", "0", "0", 
"Cat", "0", "0", "0", "Cat"), ans_2 = c("0", "Dog", "0", "0", 
"Dog", "0", "Dog", "Dog", "0", "0"), ans_3 = c("0", "0", "Sheep", 
"Sheep", "0", "0", "0", "0", "Sheep", "0"), num = c(0.44, 0.36, 
0.2, 0.72, 0.98, 0.94, 0.52, 0.84, 0.34, 0.04), size_1 = c("0", 
"0", "Big", "Big", "0", "0", "0", "0", "Big", "0"), size_2 = c("Small", 
"Small", "0", "0", "Small", "Small", "Small", "Small", "0", "Small" 
)), .Names = c("id", "ans_1", "ans_2", "ans_3", "num", "size_1", 
"size_2"), row.names = c(NA, -10L), class = "data.frame") 
1

Sie ist vielleicht unite() von tidyr verwenden möchten, und mutate_if() von dplyr dann:

library(dplyr) 
library(tidyr) 
library(stringr) 

data <- data_frame(id, ans_1, ans_2, ans_3, num, size_1, size_2) 

data %>% 
    unite(ans, ans_1, ans_2, ans_3) %>% 
    unite(size, size_1, size_2) %>% 
    mutate_if(is.character, str_extract, "[a-zA-Z]+") 

#> # A tibble: 10 × 4 
#>  id ans num size 
#> <int> <chr> <dbl> <chr> 
#> 1  1 Cat 0.92 Small 
#> 2  2 Dog 0.79 Small 
#> 3  3 Sheep 0.44 Big 
#> 4  4 Sheep 0.67 Big 
#> 5  5 Dog 0.00 Small 
#> 6  6 Cat 0.61 Small 
#> 7  7 Dog 0.67 Small 
#> 8  8 Dog 0.95 Small 
#> 9  9 Sheep 0.18 Big 
#> 10 10 Cat 0.76 Small 
0

Wie oben erwähnt, würde ein data.frame wahrscheinlich besser geeignet ..

ans<-apply(data[,2:4],1,function(x) x[x!="0"]) 
(data.new<-cbind(id=data[,1],ans,data[,5:7])) 
0

Sie können eine Funktion über ausgewählte Felder (data[, grep('ans', colnames(data))] oder data[, c('ans1', 'ans2', 'ans3')]) und fragen oder nicht gelten - 0 Werte

ans <- apply(data[, grep('ans', colnames(data))], 1, function(x) x[x!=0]) 
size <- apply(data[, grep('size', colnames(data))], 1, function(x) x[x!=0]) 

data2 <- data.frame(id, ans, num, size) 

> data2 
    id ans num size 
1 1 Cat 0.79 Small 
2 2 Dog 0.66 Small 
3 3 Sheep 0.77 Big 
4 4 Sheep 0.63 Big 
5 5 Dog 0.48 Small 
6 6 Cat 0.06 Small 
7 7 Dog 0.63 Small 
8 8 Dog 0.59 Small 
9 9 Sheep 0.24 Big 
10 10 Cat 0.96 Small 
Verwandte Themen