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