R:tapply(length) 给出与 NAs 不同的结果
R: tapply(length) giving differing results with NAs
根据我是否使用
,我使用包含 NA 的子集参数 tapply 得到不同的结果
tapply(X[X==Y], IND[X==Y], length)
或
tapply(X, IND, function(x){length(x[x==Y])})
简介:length()
NA 的行为并不符合天真的预期:
> vec <- c(1,2,3,NA,5,6,NA,8,NA,10)
> length(vec)
[1] 10
> length(is.na(vec)) # Not talking about the same vector
[1] 10
> length(vec[vec==1]) # Sometimes I forget what vector I meant
[1] 4
粗心的人会感到惊讶,但出于某种原因,它会以这种方式工作;这是预期的行为。但是上面的第二个更长的 tapply()
调用遵循这种模式,而第一个版本给出了天真的期望。
设置:
set.seed(668)
yrCodes <- c(1995:2015)
staCodes <- c(LETTERS[1:12])
sexCodes <- c('m','f')
years <- rep(yrCodes, times=rep(sample(1:4, length(yrCodes), replace=TRUE)))
stations <- sample(staCodes, length(years), replace=TRUE)
sexes <- sample(sexCodes, length(years), replace=TRUE)
sexes[sample(1:length(sexes),10)] <- NA
data <- data.frame(YEAR=years, STATION=stations, SEX=sexes)
第一种形式:
> with(data, tapply(SEX, STATION, length)) # All observations
A B C D E F G H I J K L
4 5 7 4 3 6 2 3 3 4 6 4
> with(data, tapply(SEX[SEX=='m'], STATION[SEX=='m'], length)) # Males
A B C D E F G H I J K L
2 3 4 3 NA 2 2 3 2 2 2 2
> with(data, tapply(SEX[SEX=='f'], STATION[SEX=='f'], length)) # Females
A B C D E F G H I J K L
1 1 1 NA 3 2 NA NA 1 1 3 1
> with(data, tapply(SEX[is.na(SEX)], STATION[is.na(SEX)], length)) # NAs
A B C D E F G H I J K L
1 1 2 1 NA 2 NA NA NA 1 1 1
这是粗心人所期望的,但它与上面 length(vec[])
发生的情况不符。然而,这确实:
> with(data, tapply(SEX, STATION, function(sex){length(sex[sex=='m'])})) # Males plus NAs
A B C D E F G H I J K L
3 4 6 4 0 4 2 3 2 3 3 3
> with(data, tapply(SEX, STATION, function(sex){length(sex[sex=='f'])})) # Females plus NAs
A B C D E F G H I J K L
2 2 3 1 3 4 0 0 1 2 4 2
> with(data, tapply(SEX, STATION, function(sex){length(sex[is.na(sex)])})) # NAs
A B C D E F G H I J K L
1 1 2 1 0 2 0 0 0 1 1 1
也许臭名昭著的 tapply 文档中给出了差异的原因,但我无法弄清楚。这是怎么回事?
编辑:哦,是的——我还注意到第二种方法产生零,而第一种方法只给出 NA;在调用 length
时肯定有显着差异——但是什么?
这是因为用 NA
进行子集化会得到 NA
"m" == NA
[1] NA
并且在您的通话中,您在不同的地方这样做。
考虑一下:
split(c(1,2,3), factor(c(1,2,3)))
$`1`
[1] 1
$`2`
[1] 2
$`3`
[1] 3
但因数 NA
:
split(c(1,2,3), factor(c(1,2,NA)))
$`1`
[1] 1
$`2`
[1] 2
split
自动省略 NA
,split
是 tapply
.
的主要部分
让我们看看您使用的两个 tapply
:
with(data, tapply(SEX[SEX=='m'], STATION[SEX=='m'], length))
在这里,您在 传递给 tapply
之前子集 。因此,SEX
是 NA
的 STATION
的值现在也将是 NA
,而 split
将自动忽略它们。
split(data$SEX[data$SEX == "m"], as.factor(as.numeric(data$STATION[data$SEX == "m"])))
另一个:
with(data, tapply(SEX, STATION, function(sex){length(sex[sex=='m'])}))
在这里,您在 传递给 tapply
和
之后子集
split(c(1, NA, 2), factor(c(1, 2, 3)))
当然仍会包含 NA
值。
split(data$SEX, as.factor(as.numeric(data$STATION)))
产量,例如对于第一个因素
[1] f m m <NA>
Levels: f m
而且,正如您还提到的,NA == "m"
将是 NA
。这就是为什么要这样保留 NA
的原因。
c(2, 3, 4)[c(1, NA)]
[1] 2 NA
根据我是否使用
,我使用包含 NA 的子集参数 tapply 得到不同的结果tapply(X[X==Y], IND[X==Y], length)
或
tapply(X, IND, function(x){length(x[x==Y])})
简介:length()
NA 的行为并不符合天真的预期:
> vec <- c(1,2,3,NA,5,6,NA,8,NA,10)
> length(vec)
[1] 10
> length(is.na(vec)) # Not talking about the same vector
[1] 10
> length(vec[vec==1]) # Sometimes I forget what vector I meant
[1] 4
粗心的人会感到惊讶,但出于某种原因,它会以这种方式工作;这是预期的行为。但是上面的第二个更长的 tapply()
调用遵循这种模式,而第一个版本给出了天真的期望。
设置:
set.seed(668)
yrCodes <- c(1995:2015)
staCodes <- c(LETTERS[1:12])
sexCodes <- c('m','f')
years <- rep(yrCodes, times=rep(sample(1:4, length(yrCodes), replace=TRUE)))
stations <- sample(staCodes, length(years), replace=TRUE)
sexes <- sample(sexCodes, length(years), replace=TRUE)
sexes[sample(1:length(sexes),10)] <- NA
data <- data.frame(YEAR=years, STATION=stations, SEX=sexes)
第一种形式:
> with(data, tapply(SEX, STATION, length)) # All observations
A B C D E F G H I J K L
4 5 7 4 3 6 2 3 3 4 6 4
> with(data, tapply(SEX[SEX=='m'], STATION[SEX=='m'], length)) # Males
A B C D E F G H I J K L
2 3 4 3 NA 2 2 3 2 2 2 2
> with(data, tapply(SEX[SEX=='f'], STATION[SEX=='f'], length)) # Females
A B C D E F G H I J K L
1 1 1 NA 3 2 NA NA 1 1 3 1
> with(data, tapply(SEX[is.na(SEX)], STATION[is.na(SEX)], length)) # NAs
A B C D E F G H I J K L
1 1 2 1 NA 2 NA NA NA 1 1 1
这是粗心人所期望的,但它与上面 length(vec[])
发生的情况不符。然而,这确实:
> with(data, tapply(SEX, STATION, function(sex){length(sex[sex=='m'])})) # Males plus NAs
A B C D E F G H I J K L
3 4 6 4 0 4 2 3 2 3 3 3
> with(data, tapply(SEX, STATION, function(sex){length(sex[sex=='f'])})) # Females plus NAs
A B C D E F G H I J K L
2 2 3 1 3 4 0 0 1 2 4 2
> with(data, tapply(SEX, STATION, function(sex){length(sex[is.na(sex)])})) # NAs
A B C D E F G H I J K L
1 1 2 1 0 2 0 0 0 1 1 1
也许臭名昭著的 tapply 文档中给出了差异的原因,但我无法弄清楚。这是怎么回事?
编辑:哦,是的——我还注意到第二种方法产生零,而第一种方法只给出 NA;在调用 length
时肯定有显着差异——但是什么?
这是因为用 NA
进行子集化会得到 NA
"m" == NA
[1] NA
并且在您的通话中,您在不同的地方这样做。
考虑一下:
split(c(1,2,3), factor(c(1,2,3)))
$`1`
[1] 1
$`2`
[1] 2
$`3`
[1] 3
但因数 NA
:
split(c(1,2,3), factor(c(1,2,NA)))
$`1`
[1] 1
$`2`
[1] 2
split
自动省略 NA
,split
是 tapply
.
让我们看看您使用的两个 tapply
:
with(data, tapply(SEX[SEX=='m'], STATION[SEX=='m'], length))
在这里,您在 传递给 tapply
之前子集 。因此,SEX
是 NA
的 STATION
的值现在也将是 NA
,而 split
将自动忽略它们。
split(data$SEX[data$SEX == "m"], as.factor(as.numeric(data$STATION[data$SEX == "m"])))
另一个:
with(data, tapply(SEX, STATION, function(sex){length(sex[sex=='m'])}))
在这里,您在 传递给 tapply
和
split(c(1, NA, 2), factor(c(1, 2, 3)))
当然仍会包含 NA
值。
split(data$SEX, as.factor(as.numeric(data$STATION)))
产量,例如对于第一个因素
[1] f m m <NA>
Levels: f m
而且,正如您还提到的,NA == "m"
将是 NA
。这就是为什么要这样保留 NA
的原因。
c(2, 3, 4)[c(1, NA)]
[1] 2 NA