【问题标题】:Replace values in a dataframe under specific conditions在特定条件下替换数据框中的值
【发布时间】:2017-05-06 09:44:33
【问题描述】:

我有一个数据集,我想在某些情况下替换数据集中的值。

set.seed(100)
Mydata=sample(-5:5,size = 1000,replace = T)
Mydata=as.data.frame(matrix(Mydata,nrow = 100))

Mydata[Mydata<=-1 & Mydata>-1.5] = "A"
Mydata[Mydata<=-1.5 & Mydata>-2] = "B"
Mydata[Mydata<=-2] = "C"
Mydata[Mydata>-1] = "D"

结果应该是一个用“A”、“B”、“C”和“D”填充的数据框。但是,当我运行代码时,结果只填充了“D”。我想知道问题是什么。谢谢。

【问题讨论】:

  • 您可以查看?cut
  • 谢谢。你能解释为什么我的代码是错误的。非常感谢。
  • 它基于@thelatemail 评论的覆盖。后一步的条件完全满足条件。还有cut,类似cut(Mydata, breaks = c(-Inf, -2, -1.5, -1, Inf), labels = LETTERS[1:4])
  • 按照@akrun的cut建议,试试data.frame(lapply(Mydata, cut, breaks=c(-Inf, -2, -1.5, -1, Inf), labels=c("C","B","A","D")))

标签: r dataframe replace


【解决方案1】:

问题与您将数字替换为字符这一事实有关。向量只能包含一个类的元素,因此当您在第一步中将某些元素替换为“A”时,具有这些元素的所有列都将被强制转换为字符向量。看看吧:

> set.seed(100)
> Mydata=sample(-5:5,size = 50,replace = T)
> Mydata=as.data.frame(matrix(Mydata,nrow = 10))
> str(Mydata)
'data.frame':   10 obs. of  5 variables:
 $ V1: int  -2 -3 1 -5 0 0 3 -1 1 -4
 $ V2: int  1 4 -2 -1 3 2 -3 -2 -2 2
 $ V3: int  0 2 0 3 -1 -4 3 4 1 -2
 $ V4: int  0 5 -2 5 2 4 -4 1 5 -4
 $ V5: int  -2 4 3 4 1 0 3 4 -3 -2
> Mydata[Mydata<=-1 & Mydata>-1.5] = "A"
> str(Mydata)
'data.frame':   10 obs. of  5 variables:
 $ V1: chr  "-2" "-3" "1" "-5" ...
 $ V2: chr  "1" "4" "-2" "A" ...
 $ V3: chr  "0" "2" "0" "3" ...
 $ V4: int  0 5 -2 5 2 4 -4 1 5 -4
 $ V5: int  -2 4 3 4 1 0 3 4 -3 -2

有趣的是,事实证明 R 将允许您在(不)等式测试中使用字符。因此,当您应用后续规则时,它将继续替换满足不等式的字符值,而不是抛出警告或错误。例如:

> char_vec <- c("A", 1, 2, -1)
> char_vec
[1] "A"  "1"  "2"  "-1"
> char_vec > 0
[1]  TRUE  TRUE  TRUE FALSE

事实证明所有大写字母(以及所有小写字母,就此而言)都大于 -1,因此整个矩阵最终在最后一步被 D 替换。

> toupper(letters) > -1
 [1] TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE
[19] TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE

正如 Aaghaz 所指出的,防止这种行为的最简单方法是使用 ifelse。另一种选择是创建一个新矩阵,而不是逐步覆盖原始矩阵:

> Newdata <- Mydata
> Newdata[Mydata<=-1 & Mydata>-1.5] = "A"
> Newdata[Mydata<=-1.5 & Mydata>-2] = "B"
> Newdata[Mydata<=-2] = "C"
> Newdata[Mydata>-1] = "D"

【讨论】:

  • 感谢您的帮助。你的解释很透彻!
【解决方案2】:

您可以使用ifelse

ifelse(Mydata <= -1 & Mydata > -1.5, "A",
       ifelse(Mydata <= -1.5 & Mydata > -2, "B",
              ifelse(Mydata <= -2, "C", "D")))

或者通过矢量化if,它比基本ifelse 更严格(检查真假是否为同一类型)且速度更快

if_else(Mydata <= -1 & Mydata > -1.5, "A",
           if_else(Mydata <= -1.5 & Mydata > -2, "B",
                  if_else(Mydata <= -2, "C", "D")))

【讨论】:

  • 是的,您的代码有效。你能告诉我为什么我的代码是错误的吗?谢谢。
  • 我怀疑这是因为您在每一步都不断覆盖原始Mydata,导致比较不再有意义。
  • 我认为是因为在Mydata[Mydata&lt;=-1 &amp; Mydata&gt;-1.5] = "A"这一行之后,每列的类型从int更改为chr。尝试前后运行str(Mydata)。和"-5" &gt; "-1"一样是“0”和“5”和“A”、“B”、“C”......
  • @thelatemail 非常感谢。第一步之后,Mydata 变了,有了 str 和 int。
猜你喜欢
  • 2012-11-09
  • 2021-10-10
  • 2019-01-24
  • 2019-02-25
  • 1970-01-01
  • 1970-01-01
  • 2018-08-21
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多