【问题标题】:Recode values in R在 R 中重新编码值
【发布时间】:2015-08-13 14:16:56
【问题描述】:

我想重新编码列中的值 如果 x >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 运行第二行代码时,重新编码的值恢复到以前的值。

【问题讨论】:

  • 在更新后的数据集中,条件不匹配,因为没有一个元素满足条件swl.y&gt;1 &amp; swl.y&lt;=2 示例显示
  • 刚刚编辑过,我确定我的样本中有满足条件的值。
  • 是的,现在可以 with(neu1, ifelse(swl.y&gt;1 &amp; swl.y &lt;=2, 1, swl.y)) #[1] 2.2 1.0 3.4 5.6 检查 1.2 是否被 1 替换。只需将其分配给 neu1$b &lt;- 即可创建新列
  • 您能否检查您的列sw1.y 是否为数字。即str(neu)。如果列不是数字。例如,如果是 factor ,则将其转换为数字。即neu1$sw1.y &lt;- as.numeric(as.character(neu1$sw1.y))
  • 完美,这就是我想要的,谢谢!

标签: r recode


【解决方案1】:

我们不需要为单个列循环。通过使用lapply(neu$swl.y,我们将列的每个元素作为list 元素,我们可能不需要。函数ifelse 是矢量化的,可以直接在 'swl.y' 列上使用 OP 帖子中提到的逻辑条件。

 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

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,它返回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 的编辑帖子,如果我们需要多次重新编码,请使用 cutfindInterval。在cut 中,我们可以指定breaks,还有其他参数labels 来返回或不返回默认标签。

 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))

【讨论】:

  • 不知道我的数据有什么问题,你提供的方法我都试过了,但是b还是和swl.y一模一样。我已经更新了我的数据集
  • @Lucia 我的代码中有错字。在某些地方,我输入了new 而不是neu
猜你喜欢
  • 2014-07-23
  • 2018-10-08
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多