在 R 中重新编码值
Recode values in R
我想重新编码列中的值
如果 x >1 但 < 2,它将被重新编码为 1
这是我的代码:
neu$b <- lapply(neu$swl.y, function(x) ifelse(x>1 & x<=2, 1, x))
有什么问题吗?
swl.y
2.2
1.2
3.4
5.6
我实际上需要重新编码所有值:
neu$c <- with(neu, ifelse(swl.y>1 & swl.y <=2, 1, swl.y))
neu$c <- with(neu, ifelse(swl.y>2 & swl.y <=3, 2, swl.y))
neu$c <- with(neu, ifelse(swl.y>3 & swl.y <=4, 3, swl.y))
neu$c <- with(neu, ifelse(swl.y>4 & swl.y <=5, 4, swl.y))
neu$c <- with(neu, ifelse(swl.y>5 & swl.y <=6, 5, swl.y))
neu$c <- with(neu, ifelse(swl.y>6 & swl.y <=7, 6, swl.y))
我想我知道问题出在哪里了。当 R 运行第二行代码时,重新编码的值又回到了以前的值。
我们不需要为单个列循环。通过使用 lapply(neu$swl.y
,我们将列的每个元素作为 list
元素获取,这可能是我们不需要的。函数 ifelse
是矢量化的,可以直接在具有 OP post 中提到的逻辑条件的列 'swl.y' 上使用。
neu$b <- with(neu, ifelse(swl.y>1 & swl.y <=2, 1, swl.y))
否则,我们将 'b' 列创建为 'swl.y' 并根据逻辑条件更改 'b' 的值。
neu$b <- neu$swl.y
neu$b[with(neu, swl.y>1 & swl.y <=2)] <- 1
为了更好地理解 OP 代码的问题,我们可以检查 lapply
的输出
lapply(neu$swl.y, function(x) x) #similar to `as.list(neu$swl.y)`
#[[1]]
#[1] 3
#[[2]]
#[1] 0
#[[3]]
#[1] 0
#[[4]]
#[1] 2
#[[5]]
#[1] 1
输出是一个 list
,列的每个元素都是 list
个元素。在列表上使用 ifelse
可能不是最佳选择,因为它是矢量化的(上面已经提到)。但是,假设我们使用 ifelse
lapply(neu$swl.y, function(x) ifelse(x>1 & x<=2, 1, x))
#[[1]]
#[1] 3
#[[2]]
#[1] 0
#[[3]]
#[1] 0
#[[4]]
#[1] 1
#[[5]]
#[1] 1
A data.frame
可以被视为具有相同长度的列表元素的 list
。所以,根据上面的输出,这应该是一个有 5 列和 1 行的 data.frame。通过分配给单个列 'b',我们创建了一个包含 5 个列表元素的 list
列。
neu$b <- lapply(neu$swl.y, function(x) ifelse(x>1 & x<=2, 1, x))
str(neu)
#'data.frame': 5 obs. of 2 variables:
#$ swl.y: int 3 0 0 2 1
#$ b :List of 5
# ..$ : int 3
# ..$ : int 0
# ..$ : int 0
# ..$ : num 1
# ..$ : int 1
但是,这不是我们想要的。补救措施是什么?一种方法是使用 sapply/vapply
而不是 lapply
,其中 return 是 vector
输出,因为长度相同,或者我们 unlist
将 lapply
输出到创建一个 vector
neu$b <- sapply(neu$swl.y, function(x) ifelse(x>1 & x<=2, 1, x))
str(neu)
#'data.frame': 5 obs. of 2 variables:
# $ swl.y: int 3 0 0 2 1
# $ b : num 3 0 0 1 1
更新
根据 OP 编辑的 post,如果我们需要多次重新编码,请使用 cut
或 findInterval
。在 cut
中,我们可以指定 breaks
并且还有其他参数 labels
到 return 是否为默认标签。
with(neu1, cut(swl.y, breaks=c(-Inf,1,2,3,4,5,6,Inf), labels=F)-1)
#[1] 2 1 3 5
数据
set.seed(48)
neu <- data.frame(swl.y=sample(0:5, 5, replace=TRUE))
#newdata
neu1 <- structure(list(swl.y = c(2.2, 1.2, 3.4, 5.6)),
.Names = "swl.y", class = "data.frame", row.names = c(NA, -4L))
我想重新编码列中的值 如果 x >1 但 < 2,它将被重新编码为 1
这是我的代码:
neu$b <- lapply(neu$swl.y, function(x) ifelse(x>1 & x<=2, 1, x))
有什么问题吗?
swl.y
2.2
1.2
3.4
5.6
我实际上需要重新编码所有值:
neu$c <- with(neu, ifelse(swl.y>1 & swl.y <=2, 1, swl.y))
neu$c <- with(neu, ifelse(swl.y>2 & swl.y <=3, 2, swl.y))
neu$c <- with(neu, ifelse(swl.y>3 & swl.y <=4, 3, swl.y))
neu$c <- with(neu, ifelse(swl.y>4 & swl.y <=5, 4, swl.y))
neu$c <- with(neu, ifelse(swl.y>5 & swl.y <=6, 5, swl.y))
neu$c <- with(neu, ifelse(swl.y>6 & swl.y <=7, 6, swl.y))
我想我知道问题出在哪里了。当 R 运行第二行代码时,重新编码的值又回到了以前的值。
我们不需要为单个列循环。通过使用 lapply(neu$swl.y
,我们将列的每个元素作为 list
元素获取,这可能是我们不需要的。函数 ifelse
是矢量化的,可以直接在具有 OP post 中提到的逻辑条件的列 'swl.y' 上使用。
neu$b <- with(neu, ifelse(swl.y>1 & swl.y <=2, 1, swl.y))
否则,我们将 'b' 列创建为 'swl.y' 并根据逻辑条件更改 'b' 的值。
neu$b <- neu$swl.y
neu$b[with(neu, swl.y>1 & swl.y <=2)] <- 1
为了更好地理解 OP 代码的问题,我们可以检查 lapply
lapply(neu$swl.y, function(x) x) #similar to `as.list(neu$swl.y)`
#[[1]]
#[1] 3
#[[2]]
#[1] 0
#[[3]]
#[1] 0
#[[4]]
#[1] 2
#[[5]]
#[1] 1
输出是一个 list
,列的每个元素都是 list
个元素。在列表上使用 ifelse
可能不是最佳选择,因为它是矢量化的(上面已经提到)。但是,假设我们使用 ifelse
lapply(neu$swl.y, function(x) ifelse(x>1 & x<=2, 1, x))
#[[1]]
#[1] 3
#[[2]]
#[1] 0
#[[3]]
#[1] 0
#[[4]]
#[1] 1
#[[5]]
#[1] 1
A data.frame
可以被视为具有相同长度的列表元素的 list
。所以,根据上面的输出,这应该是一个有 5 列和 1 行的 data.frame。通过分配给单个列 'b',我们创建了一个包含 5 个列表元素的 list
列。
neu$b <- lapply(neu$swl.y, function(x) ifelse(x>1 & x<=2, 1, x))
str(neu)
#'data.frame': 5 obs. of 2 variables:
#$ swl.y: int 3 0 0 2 1
#$ b :List of 5
# ..$ : int 3
# ..$ : int 0
# ..$ : int 0
# ..$ : num 1
# ..$ : int 1
但是,这不是我们想要的。补救措施是什么?一种方法是使用 sapply/vapply
而不是 lapply
,其中 return 是 vector
输出,因为长度相同,或者我们 unlist
将 lapply
输出到创建一个 vector
neu$b <- sapply(neu$swl.y, function(x) ifelse(x>1 & x<=2, 1, x))
str(neu)
#'data.frame': 5 obs. of 2 variables:
# $ swl.y: int 3 0 0 2 1
# $ b : num 3 0 0 1 1
更新
根据 OP 编辑的 post,如果我们需要多次重新编码,请使用 cut
或 findInterval
。在 cut
中,我们可以指定 breaks
并且还有其他参数 labels
到 return 是否为默认标签。
with(neu1, cut(swl.y, breaks=c(-Inf,1,2,3,4,5,6,Inf), labels=F)-1)
#[1] 2 1 3 5
数据
set.seed(48)
neu <- data.frame(swl.y=sample(0:5, 5, replace=TRUE))
#newdata
neu1 <- structure(list(swl.y = c(2.2, 1.2, 3.4, 5.6)),
.Names = "swl.y", class = "data.frame", row.names = c(NA, -4L))