在特定条件下替换数据框中的值

时间:2016-12-21 03:49:11

标签: r dataframe replace

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

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”填充。我想知道问题是什么。感谢。

enter image description here

2 个答案:

答案 0 :(得分:3)

问题与您用字符替换数字这一事实有关。向量只能包含一个类的元素,所以当你用&#34; A&#34;替换一些元素时。在第一步中,具有这些元素的所有列都被强制转换为字符向量。看看:

> 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允许你在(in)相等的测试中使用字符。因此,当您应用后续规则时,它将继续替换满足不等式的字符值,而不是抛出警告或错误。例如:

> 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

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

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

答案 1 :(得分:2)

您可以使用ifelse

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

或者更严格的矢量化if(检查true和false是同一类型)并且比base ifelse更快

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