中位数的函数类似于"which.max"和"which.min"/从data.frame中提取中值行

A5C*_*2T1 8 r subset dataframe

我偶尔需要根据其中一个变量的值从data.frame中提取特定的行.R具有maximum(which.max())和minimum(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), ]
Run Code Online (Sandbox Code Playgroud)

对于这个特定的例子,由于存在偶数个观察,我需要返回两行,在这种情况下,行2和10.

更新

似乎没有内置功能.因此,使用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]))
  }
}
Run Code Online (Sandbox Code Playgroud)

我可以按如下方式使用它:

# 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), ]
Run Code Online (Sandbox Code Playgroud)

有什么建议可以改善吗?

cbe*_*ica 15

虽然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]
}
Run Code Online (Sandbox Code Playgroud)

一点测试:

> 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 
Run Code Online (Sandbox Code Playgroud)

这是你的例子:

> 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
Run Code Online (Sandbox Code Playgroud)


Sac*_*amp 9

我想:

which(dat$V4 == median(dat$V4))
Run Code Online (Sandbox Code Playgroud)

但要小心,因为如果没有一个中间数,中位数取两个数的平均值.例如,median(1:4)给出2.5与任何元素都不匹配的.

编辑

这是一个函数,它将为您提供中位数的元素或与中位数均值的第一个匹配,类似于如何which.min()为您提供仅等于最小值的第一个元素:

whichmedian <- function(x) which.min(abs(x - median(x)))
Run Code Online (Sandbox Code Playgroud)

例如:

> whichmedian(1:4)
[1] 2
Run Code Online (Sandbox Code Playgroud)