在下面编码的R数据框中,我想替换B
的所有时间
与b
一起显示。
junk <- data.frame(x <- rep(LETTERS[1:4], 3), y <- letters[1:12])
colnames(junk) <- c("nm", "val")
这提供了:
nm val
1 A a
2 B b
3 C c
4 D d
5 A e
6 B f
7 C g
8 D h
9 A i
10 B j
11 C k
12 D l
我最初的尝试是使用for
和if
语句,如下所示:
for(i in junk$nm) if(i %in% "B") junk$nm <- "b"
但我确信您可以看到,这会将junk$nm
的所有值替换为b
。我可以看到为什么这样做但我似乎无法让它只替换那些原始值为B
的垃圾$ nm的情况。
注意:我设法用gsub
来解决问题,但为了学习R,我仍然想知道如何让我的原始方法工作(如果可能的话)
答案 0 :(得分:176)
更容易将nm转换为字符,然后进行更改:
junk$nm <- as.character(junk$nm)
junk$nm[junk$nm == "B"] <- "b"
编辑:如果确实需要维持nm作为因子,最后添加:
junk$nm <- as.factor(junk$nm)
答案 1 :(得分:33)
替换值的另一种有用方法
library(plyr)
junk$nm <- revalue(junk$nm, c("B"="b"))
答案 2 :(得分:24)
简短回答是:
junk$nm[junk$nm %in% "B"] <- "b"
看看Index vectors in R Introduction(如果你还没看过)。
EDIT。正如评论中所注意到的,这个解决方案适用于字符向量,因此对数据失败。
因为最好的方法是改变等级:
levels(junk$nm)[levels(junk$nm)=="B"] <- "b"
答案 3 :(得分:19)
由于您显示的数据是因素,因此会使事情变得复杂。 @diliop的答案通过将nm
转换为字符变量来解决问题。要回到原始因素,需要采取进一步措施。
另一种方法是操纵因素的水平。
> lev <- with(junk, levels(nm))
> lev[lev == "B"] <- "b"
> junk2 <- within(junk, levels(nm) <- lev)
> junk2
nm val
1 A a
2 b b
3 C c
4 D d
5 A e
6 b f
7 C g
8 D h
9 A i
10 b j
11 C k
12 D l
这很简单,我经常忘记levels()
有替代功能。
编辑正如@Seth在评论中指出的那样,这可以在单行中完成,而不会失去清晰度:
within(junk, levels(nm)[levels(nm) == "B"] <- "b")
答案 4 :(得分:11)
在一个命令中执行此操作的最简单方法是使用which
命令,也不需要通过执行以下操作将因子更改为字符:
junk$nm[which(junk$nm=="B")]<-"b"
答案 5 :(得分:5)
您已在nm
中创建了一个因子变量,因此您需要避免这样做,或者为因子属性添加额外的级别。您还应该避免在data.frame()
<-
选项1:
junk <- data.frame(x = rep(LETTERS[1:4], 3), y =letters[1:12], stringsAsFactors=FALSE)
junk$nm[junk$nm == "B"] <- "b"
选项2:
levels(junk$nm) <- c(levels(junk$nm), "b")
junk$nm[junk$nm == "B"] <- "b"
junk
答案 6 :(得分:1)
如果您正在处理字符变量(请注意此处stringsAsFactors
为false),您可以使用replace:
junk <- data.frame(x <- rep(LETTERS[1:4], 3), y <- letters[1:12], stringsAsFactors = FALSE)
colnames(junk) <- c("nm", "val")
junk$nm <- replace(junk$nm, junk$nm == "B", "b")
junk
# nm val
# 1 A a
# 2 b b
# 3 C c
# 4 D d
# ...
答案 7 :(得分:0)
stata.replace<-function(data,replacevar,replacevalue,ifs) {
ifs=parse(text=ifs)
yy=as.numeric(eval(ifs,data,parent.frame()))
x=sum(yy)
data=cbind(data,yy)
data[yy==1,replacevar]=replacevalue
message=noquote(paste0(x, " replacement are made"))
print(message)
return(data[,1:(ncol(data)-1)])
}
在下面的行中调用此函数。
d=stata.replace(d,"under20",1,"age<20")
答案 8 :(得分:0)
您也可以使用ifelse
,非常简单易懂
junk$val <- ifelse(junk$nm == "B", "b", junk$val)
如果你还想通过for loop
正确的做法
for(i in 1:nrow(junk)){
if(junk[i, "nm"] == "B"){
junk[i, "val"] <- "b"
}
}
junk
> junk
nm val
1 A a
2 B b
3 C c
4 D d
5 A e
6 B b
7 C g
8 D h
9 A i
10 B b
11 C k
12 D l
答案 9 :(得分:0)
我遇到了同样的问题,你也可以对每一列做同样的事情,
fix_junk <- function(x){
#x <- as.character(x)
x[x == "B"] <- "b"
x
}
junk[] <- lapply(junk, fix_junk); junk # junk[] to get a data frame rather than a list
junk[1:3] <- lapply(junk[1:3], fix_junk); junk