Ich muss einige Werte in meinem Datenrahmen ändern, die über Zeilen iterieren. Wenn für eine Zeile in einer Spalte eine 1 vorhanden ist, muss ich in anderen Spalten 0 Werte in NA ändern.

Ich habe einen Code, der funktioniert, aber bei Verwendung eines größeren Datensatzes sehr langsam ist.

data = data.frame(id=c("A","B","C"),V1=c(1,0,0),V2=c(0,0,0),V3=c(1,0,1))
cols = names(data)[2:4]

for (i in 1:nrow(data)){
  if(any(data[i,cols]==1)){
    data[i,cols][data[i,cols]==0]=NA
  }
}

Ich habe einen Beispieldatensatz

data
  id V1 V2 V3
1  A  1  0  1
2  B  0  0  0
3  C  0  0  1

Und das erwartete (und das tatsächliche) Ergebnis ist

data
  id V1 V2 V3
1  A  1 NA  1
2  B  0  0  0
3  C NA NA  1

Wie kann ich das optimaler schreiben?

0
user570271 18 Jän. 2019 im 17:11

3 Antworten

Beste Antwort

Ein Einzeiler kann sein,

data[rowSums(data[-1]) > 0,] <- replace(data[rowSums(data[-1]) > 0,], 
                                        data[rowSums(data[-1]) > 0,] == 0, 
                                        NA)
data
#  id V1 V2 V3
#1  A  1 NA  1
#2  B  0  0  0
#3  C NA NA  1

Um zu vermeiden, dass derselbe Ausdruck immer wieder ausgewertet wird, können wir ihn zuerst definieren, d. H.

v1 <- rowSums(data[-1]) > 0
data[v1,] <- replace(data[v1,], 
                     data[v1,] == 0, 
                     NA)
0
Sotos 18 Jän. 2019 im 15:37

Mit dplyr ist es einfach, vorausgesetzt, Sie möchten die Werte für die Spalten V1 und V2 basierend auf den Werten in V3 ändern. Wir können Spalten angeben, für die wir Werte ändern möchten, in mutate_at und im Argument funs die Bedingung angeben, für die Sie Werte ändern möchten.

library(dplyr)

data %>% mutate_at(vars(V1:V2), funs(replace(., V3 == 1 & . == 0, NA)))

#  id V1 V2 V3
#1  A  1 NA  1
#2  B  0  0  0
#3  C NA NA  1
0
Ronak Shah 18 Jän. 2019 im 14:16

Wir können dies in base R tun, indem wir mit rowSums einen logischen Vektor erstellen und dann die numerischen Spalten basierend auf diesem Index aktualisieren

i1 <- rowSums(data[-1] == 1) > 0
data[-1][i1,] <- NA^ !data[-1][i1,]
data
#  id V1 V2 V3
#1  A  1 NA  1
#2  B  0  0  0
#3  C NA NA  1

Wenn der Index auf einer einzelnen Spalte basieren muss, z. B. 'V3', ändern Sie 'i1' in

i1 <- data$V3 == 1

Und aktualisieren Sie die anderen numerischen Spalten, nachdem Sie die Zeilen mit 'i1' untergeordnet haben, und erstellen Sie eine logische Matrix mit Negation (! - gibt TRUE für 0-Werte und alle anderen FALSE zurück). Wenn Sie dann NA^ für die logische Matrix verwenden, wird NA für TRUE und 1 für andere Werte zurückgegeben. Da es nur Binärwerte gibt, kann dies aktualisiert werden

data[i1, 2:3] <- NA^!data[i1, 2:3]
0
akrun 18 Jän. 2019 im 14:28