这个R语法是如何工作的?在for循环中通过[apply()with match()]选择性地使用gsub()

这个R语法是如何工作的?在for循环中通过[apply()with match()]选择性地使用gsub(),r,syntax,match,apply,gsub,R,Syntax,Match,Apply,Gsub,不久前,我改编了StackOverflow的一些代码,但是我一直找不到原始的帖子。代码对我的应用程序来说很好,但我并不真正“理解”语法。(通过将数字数据值与“new_labels”向量中的相应值进行匹配,代码将覆盖具有特定字符串的数据中的数值。该匹配是特定于列的。) 参考下面的代码,有人能解释一下如何使用[apply]子句来指定gsub()在何处进行替换吗?换句话说,这个语法是如何工作的?为什么apply会影响gsub()?更好的是,有没有一种更简单的方法来处理这个问题 # reproducib

不久前,我改编了StackOverflow的一些代码,但是我一直找不到原始的帖子。代码对我的应用程序来说很好,但我并不真正“理解”语法。(通过将数字数据值与“new_labels”向量中的相应值进行匹配,代码将覆盖具有特定字符串的数据中的数值。该匹配是特定于列的。)

参考下面的代码,有人能解释一下如何使用[apply]子句来指定gsub()在何处进行替换吗?换句话说,这个语法是如何工作的?为什么apply会影响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]])] <- ""
}
#可复制示例
#假数据

dat让我们把它从循环中拉出来,看看到底发生了什么

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
是MARGIN,
?match
是它正在应用的函数,
X=j
match
循环的一部分,介于
1
2
之间(来自
中的(1:2中的j)
)。如中所示,如果它找到了
1
的匹配项,则替换为
1

apply(dat[,variables[1]], 1, match, x = 1)
 [1]  1 NA  1  1  1 NA  1 NA  1  1
gsub
将第一个
新标签
名称
(elf)
替换为第一个
变量
名称
(var1)
,并将其写入
字母[i]
字母[1]
a
)的匹配元素。因此,它在匹配
a
的列中的
llist
(名为
ones
)的第一个
列表
元素中找到一个匹配项

它对每个标签的所有
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

dat2让我们把它从循环中拉出来,看看到底发生了什么

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
是MARGIN,
?match
是它正在应用的函数,
X=j
match
循环的一部分,介于
1
2
之间(来自
中的(1:2中的j)
)。如中所示,如果它找到了
1
的匹配项,则替换为
1

apply(dat[,variables[1]], 1, match, x = 1)
 [1]  1 NA  1  1  1 NA  1 NA  1  1
gsub
将第一个
新标签
名称
(elf)
替换为第一个
变量
名称
(var1)
,并将其写入
字母[i]
字母[1]
a
)的匹配元素。因此,它在匹配
a
的列中的
llist
(名为
ones
)的第一个
列表
元素中找到一个匹配项

它对每个标签的所有
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

dat2这里有很多嵌套,但要理解函数,最好的方法是在控制台中运行嵌套最多的部分并向外工作

假设i=1,j=1

apply(dat[,变量[i]],1,match,x=j)
apply被提供一个子集数据,即“var1”列。然后match应用于该列的每个索引,如果索引中的值与x参数匹配,则返回1,否则返回NA

这个向量被称为
vec
,然后被传递到
名称(dat[,variables[i]])[vec]

names(dat[,variables[i]])
似乎只是返回
variable[i]
,因此在本例中似乎没有什么意义

名称(dat[,变量[i]])[vec]
vec
中的每个1值替换为
variables[i]

最后,在
gsub(pattern=variables[i],new_labels[i],new.vec)中


其中
new.vec
names(dat[,variables[i]]),[vec]

这里有很多嵌套,但要理解函数,最好的方法是在控制台中运行嵌套最多的部分并向外工作

假设i=1,j=1

apply(dat[,变量[i]],1,match,x=j)
apply被提供一个子集数据,即“var1”列。然后match应用于该列的每个索引,如果索引中的值与x参数匹配,则返回1,否则返回NA

这个向量被称为
vec
,然后被传递到
名称(dat[,variables[i]])[vec]

names(dat[,variables[i]])
似乎只是返回
variable[i]
,因此在本例中似乎没有什么意义

名称(dat[,变量[i]])[vec]
vec
中的每个1值替换为
variables[i]

最后,在
gsub(pattern=variables[i],new_labels[i],new.vec)中


其中
new.vec
名称(dat[,variables[i]])[vec]

谢谢您的精彩解释!我很难理解apply()在做什么,因为我不知道向量可以通过这种方式传递给gsub()。但除此之外,当你说
名称(dat[,variables[i]])
,子句有点毫无意义,这是否意味着你怀疑它可以简化为
变量[i]
?非常感谢。不客气,我只说一点代码可能毫无意义,因为根据我自己在本例中的故障排除,它
variable[I]
可以正常工作。我没有试着去想
名称(dat[,variables[I]]