Как работает этот синтаксис R?Выборочное использование gsub () функцией [apply () с match ()] внутри цикла for - PullRequest
0 голосов
/ 26 сентября 2018

Некоторое время назад я адаптировал некоторый код из StackOverflow, но мне не удалось найти оригинальный пост.Код отлично работает для моих приложений, но я не совсем понимаю синтаксис.(Код перезаписывает числовые значения в данных конкретными символьными строками, сопоставляя числовое значение данных с соответствующим значением в векторе 'new_labels'. Соответствие зависит от столбца.)

Обращаясь к приведенному ниже коду, может кто-нибудьобъясните, как выражение [apply] используется, чтобы указать, где gsub () выполняет замены?Или, другими словами, как работает этот синтаксис?Почему применение влияет на gsub () здесь?А еще лучше, есть ли более простой подход к этому действию?

# reproducible example
# fake data           
    dat <- tibble(var1 = c(1,NA, 1,1,1,2,1,NA,1,1),
                  var2 = c(NA,1,NA,NA,NA,NA,NA,1,NA,NA),
                  var3 = c(2,2,NA,2,NA,1,2,NA,NA,NA),
                  var4 = c(NA,NA,2,NA,2,NA,NA,2,2,2)) 
# names of columns in fake data
variables <- names(dat)
# names of new labels to replace the numeric values
new_labels <- c("elf", "hobbit", "wizard", "ranger")      
# empty list
    llist <- list(ones = data.frame(matrix(ncol=4,nrow=10)),
                  twos = data.frame(matrix(ncol=4,nrow=10)))
    names(llist[[1]]) <- letters[1:length(new_labels)]
    names(llist[[2]]) <- letters[1:length(new_labels)]
# for loops
    for(j in 1:2){   
        for(i in 1:length(new_labels)){
            llist[[j]][, letters[i]] <- gsub(variables[i], new_labels[i], names(dat[,variables[i]]))[apply(dat[,variables[i]], 1, match, x= j)]
    }
        llist[[j]][is.na(llist[[j]])] <- ""
}

Ответы [ 2 ]

0 голосов
/ 26 сентября 2018

Здесь много вложений, но для понимания функций лучший способ - запустить наиболее вложенную часть в вашей консоли и работать за ее пределами.

давайте предположим, что i = 1 и j = 1

apply(dat[,variables[i]], 1, match, x= j) apply - это подмножество данных, а именно столбец «var1».Затем сопоставление применяется к каждому индексу этого столбца, возвращая 1, если значение в индексе соответствует аргументу x, а в противном случае возвращается NA.

этот вектор, давайте вызовем его vec, затем передается names(dat[,variables[i]]))[vec].

names(dat[,variables[i]]), кажется, просто возвращает variable[i], поэтому в этом примере это выглядит немного бессмысленно.

names(dat[,variables[i]]))[vec] заменяет каждое 1 значение в vec значением в variables[i]

наконец, в gsub(pattern = variables[i], new_labels[i], new.vec), где new.vec равно names(dat[,variables[i]]))[vec]

0 голосов
/ 26 сентября 2018

Давайте вытянем его из цикла и посмотрим, что именно происходит.

gsub(variables[1], new_labels[1], names(dat[,variables[1]]))[apply(dat[,variables[1]], 1, match, x = 1)]
[1] "elf" NA    "elf" "elf" "elf" NA    "elf" NA    "elf" "elf"

Глядя на справку для ?apply: apply(X, MARGIN, FUN, ...), где x - столбец dat мы зациклились на первом, 1 - это поле, ?match - это функция, которую она применяет, а x = j - это часть цикла для match, между 1 и 2 (из for(j in 1:2)).Например, если он находит совпадение для 1, замените его на 1.

apply(dat[,variables[1]], 1, match, x = 1)
 [1]  1 NA  1  1  1 NA  1 NA  1  1

И gsub заменяет первое new_labels имя (elf) на первое variables name (var1) и записывает его в соответствующий элемент letters[i] (letters[1] is a).Таким образом, он находит совпадение в первом list элементе llist (с именем ones) в столбце, соответствующем a.

. Он повторяет это для всех значений 1 для каждой метки, затемдля каждого элемента списка, затем для всех 2 значений и т. д. Первая строка превращается во вторую.

[1]  1    NA   1     1     1    NA     1    NA     1     1
[1] "elf" NA  "elf" "elf" "elf" NA    "elf" NA    "elf" "elf"

Это довольно элегантный процесс.

Вот пошаговая инструкция-шаг без цикла, так что вы можете увидеть, что делает цикл.

dat2 <- as.data.frame(dat)
names(dat2) <- new_labels
dat2 <- list(dat2, dat2)
dat2[[1]][dat2[[1]] == 2] <- NA
dat2[[2]][dat2[[2]] == 1] <- NA
w1 <- which(dat2[[1]] == TRUE, arr.ind = TRUE)
w2 <- which(dat2[[2]] == 2, arr.ind = TRUE)
dat2[[1]][w1] <- colnames(dat2[[1]])[w1[,"col"]]
dat2[[2]][w2] <- colnames(dat2[[2]])[w2[,"col"]]
dat2 <- lapply(dat2, function(x) { x[is.na(x)] <- "" ; x})

[[1]]
   elf hobbit wizard ranger
1  elf                     
2      hobbit              
3  elf                     
4  elf                     
5  elf                     
6             wizard       
7  elf                     
8      hobbit              
9  elf                     
10 elf                     

[[2]]
   elf hobbit wizard ranger
1             wizard       
2             wizard       
3                    ranger
4             wizard       
5                    ranger
6  elf                     
7             wizard       
8                    ranger
9                    ranger
10                   ranger
...