我有时需要根据其中一个变量的值从data.frame中提取特定的行。 R
具有最大(which.max()
)和最小(which.min()
)的内置函数,这些函数使我可以轻松提取这些行。
中位数是否相等?还是我最好的选择就是编写自己的函数?
这是一个示例data.frame以及我将如何使用which.max()
和which.min()
:
set.seed(1) # so you can reproduce this example
dat = data.frame(V1 = 1:10, V2 = rnorm(10), V3 = rnorm(10),
V4 = sample(1:20, 10, replace=T))
# To return the first row, which contains the max value in V4
dat[which.max(dat$V4), ]
# To return the seventh row, which contains the min value in V4
dat[which.min(dat$V4), ]
对于这个特定的示例,由于观察到的偶数个数,我需要返回两行,在这种情况下,是第2行和第10行。
更新
似乎没有为此内置的功能。这样,以reply from Sacha为起点,我编写了以下函数:
which.median = function(x) {
if (length(x) %% 2 != 0) {
which(x == median(x))
} else if (length(x) %% 2 == 0) {
a = sort(x)[c(length(x)/2, length(x)/2+1)]
c(which(x == a[1]), which(x == a[2]))
}
}
我可以按以下方式使用它:
# make one data.frame with an odd number of rows
dat2 = dat[-10, ]
# Median rows from 'dat' (even number of rows) and 'dat2' (odd number of rows)
dat[which.median(dat$V4), ]
dat2[which.median(dat2$V4), ]
有什么建议可以改善吗?
最佳答案
虽然Sacha的解决方案相当笼统,但中位数(或其他分位数)是顺序统计信息,因此您可以根据order (x)
(而不是sort (x)
的分位数值)计算相应的索引。
查看quantile
,可以使用类型1或3,在某些情况下,所有其他类型都会得出(加权)两个值的平均值。
我选择了类型3,然后从quantile
中进行了一些复制和粘贴操作导致:
which.quantile <- function (x, probs, na.rm = FALSE){
if (! na.rm & any (is.na (x)))
return (rep (NA_integer_, length (probs)))
o <- order (x)
n <- sum (! is.na (x))
o <- o [seq_len (n)]
nppm <- n * probs - 0.5
j <- floor(nppm)
h <- ifelse((nppm == j) & ((j%%2L) == 0L), 0, 1)
j <- j + h
j [j == 0] <- 1
o[j]
}
一点测试:
> x <-c (2.34, 5.83, NA, 9.34, 8.53, 6.42, NA, 8.07, NA, 0.77)
> probs <- c (0, .23, .5, .6, 1)
> which.quantile (x, probs, na.rm = TRUE)
[1] 10 1 6 6 4
> x [which.quantile (x, probs, na.rm = TRUE)] == quantile (x, probs, na.rm = TRUE, type = 3)
0% 23% 50% 60% 100%
TRUE TRUE TRUE TRUE TRUE
这是您的示例:
> dat [which.quantile (dat$V4, c (0, .5, 1)),]
V1 V2 V3 V4
7 7 0.4874291 -0.01619026 1
2 2 0.1836433 0.38984324 13
1 1 -0.6264538 1.51178117 17
关于r - 中位数的函数类似于 "which.max"和 "which.min"/从data.frame中提取中位数行,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/10256503/