我有一个包含 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
这里有一些提示。在 R 中,通常使用<-
运算符将变量分配给名称。公平地说,我甚至不知道你可以为变量分配长度,所以我学到了一些新东西。
A <- seq(1, 6)
length(A) <- 7
B <- seq(2, 4)
length(B) <- 7
m <- cbind(A, B)
matrix
和data.frame
之间的区别在于,矩阵是数字向量,其dim
属性指定维度(数组也是如此(,而 data.frame 是一系列长度相等的列表(沿列((行数(。
这在实践中意味着data.frame可以在不同的列中有任何内容,例如,一个可能是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 语句不起作用,因为它们不是矢量化的:它们需要单个TRUE
或FALSE
,而不是逻辑向量。您可以通过计算表达式来查看表达式比 1 长,并询问长度:
> 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]
这给了你这个数据帧:
> 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
有多种其他选项可以获得相同的结果,但我认为按名称进行子集是相对直观的。
你似乎是R的新手。随着你的继续,你会发现,在R中,有些事情的完成方式与其他语言完全不同。
例如,要根据您的条件设置列C
,您需要执行以下操作:
df$C = ifelse(
df$Acat=="low", 1, ifelse(
df$Acat=="mod", 2, ifelse(
df$Acat=="hi", 3, NA
)))
如果您正在使用 tidyverse,您也可以使用 case_when。