在[r]中缺少值的数据中,如何使用多个关系运算符将值分配给新变量?

时间:2019-12-16 15:28:09

标签: r

我有一个包含20个变量的数据集,并且缺少很多数据。我试图添加一个新的变量,并根据另一个变量的值为每一行分配一个值。下面是代码和一个较小的数据集,与我的较大数据集给出的错误相同。有什么建议么?

A=seq(1,6); B=seq(2,4)
length(A)=7; length(B)=7
m=cbind(A,B)

我不完全理解从矩阵到数据帧的转换。

df=as.data.frame(m)
df

首先尝试创建分类变量,以便在分配新变量的值时使用

df$Acat=cut(df$A,
              breaks=c(-Inf,2.5,4.5,Inf),
              labels=c("low","mod","hi"))
df$Acat

下面的代码是我收到错误信息“:参数的长度为零”

if (df$Acat.=="low"){
  df$C=1
}else if (df$Acat.=="mod"){
  df$C=2
}else if(df$Acat.=="hi"){
  df$C=3
}else {
  df$C=NA
}
df$C

我也这样尝试过,使用数字变量来分配新变量的值,但出现此错误:

  

条件的长度> 1,并且仅使用第一个元素

if (df$A<2.5){
  df$D=1
} else if (df$A>=2.5 && df$A<4.5){
  df$D=2
} else if (df$A>=4.5){
  df$D=3
} else {
  df$D=NA
}
df$D

2 个答案:

答案 0 :(得分:0)

您似乎对R并不陌生。随着您的继续,您会发现R中的某些事情与其他语言完全不同。

例如,要根据您的条件设置列C,您可以这样做:

df$C = ifelse(
  df$Acat=="low", 1, ifelse(
    df$Acat=="mod", 2, ifelse(
     df$Acat=="hi", 3, NA 
    )))

如果您正在使用tidyverse,也可以使用case_when

答案 1 :(得分:0)

这里有一些指针。在R中,通常使用<-运算符将变量分配给名称。公平地说,我什至不知道您可以为变量分配长度,所以我学到了一些新知识。

A <- seq(1, 6)
length(A) <- 7
B <- seq(2, 4)
length(B) <- 7

m <- cbind(A, B)

matrixdata.frame之间的区别在于,矩阵是具有dim属性指定维数(对于数组也是如此)的数字向量。框架是一系列等长(行数)的列表(沿列)。

实际上,这意味着data.frames可以在不同的列中包含任何内容,例如一个可能是character,另一个可能是integer,而矩阵只能包含相同类型的数据。

> attributes(m)
$dim
[1] 7 2

$dimnames
$dimnames[[1]]
NULL

$dimnames[[2]]
[1] "A" "B"
> df <- as.data.frame(m)
> attributes(df)
$names
[1] "A" "B"

$class
[1] "data.frame"

$row.names
[1] 1 2 3 4 5 6 7

> is.list(m)
[1] FALSE
> is.list(df)
[1] TRUE

您用来尝试将值分配给列的if-else语句不起作用,因为它们没有向量化:它们需要单个TRUEFALSE,而不是逻辑向量。通过求值,您可以看到表达式长于一个:

> df$Acat == "low"
[1]  TRUE  TRUE FALSE FALSE FALSE FALSE    NA

> length(df$Acat == "low")
[1] 7

相反,您可以使用所需的值构建命名向量,并使用子设置操作将其放置在正确的位置:

df$Acat <- cut(df$A,
            breaks=c(-Inf,2.5,4.5,Inf),
            labels=c("low","mod","hi"))

named_vec <- c("low" = 1, "mod" = 2, "hi" = 3)
df$C <- named_vec[df$Acat]

哪个为您提供此data.frame:

> df
   A  B Acat  C
1  1  2  low  1
2  2  3  low  1
3  3  4  mod  2
4  4 NA  mod  2
5  5 NA   hi  3
6  6 NA   hi  3
7 NA NA <NA> NA

还有多个其他选项可以得到相同的结果,但是我认为按名称进行子集比较直观。