使用NA计算列中位数

4
我正在尝试在R中计算每个列的中位数,然后将中位数值与该列中的每个值相减。我面临的问题是该列中存在N/A值,我不想将其删除,而只是返回它们而不进行中位数减法运算。例如:
ID <- c("A","B","C","D","E") 
Point_A <- c(1, NA, 3, NA, 5) 
Point_B <- c(NA, NA, 1, 3, 2)

df <- data.frame(ID,Point_A ,Point_B)

在一个包含N/A的列中计算中位数是否可能?我的输出结果将是

+----+---------+---------+
| ID | Point_A | Point_B |
+----+---------+---------+
| A  | -2      | NA      |
| B  | NA      | NA      |
| C  | 0       | -1      |
| D  | NA      | 1       |
| E  | 2       | 0       |
+----+---------+---------+

如果您不介意,我已将其编辑为数字值。 - David Arenburg
@David 没问题。 - Sharath
3个回答

6
如果我们说的是真正的NA值(根据OPs评论),可以这样做:
df[-1] <- lapply(df[-1], function(x) x - median(x, na.rm = TRUE))
df
#   ID Point_A Point_B
# 1  A      -2      NA
# 2  B      NA      NA
# 3  C       0      -1
# 4  D      NA       1
# 5  E       2       0

或者使用 matrixStats

library(matrixStats)
df[-1] <- df[-1] - colMedians(as.matrix(df[-1]), na.rm = TRUE)

当原始的df为:
df <- structure(list(ID = structure(1:5, .Label = c("A", "B", "C", 
"D", "E"), class = "factor"), Point_A = c(1, NA, 3, NA, 5), Point_B = c(NA, 
NA, 1, 3, 2)), .Names = c("ID", "Point_A", "Point_B"), row.names = c(NA, 
-5L), class = "data.frame")

这是我第一次看到 matrixStats。很酷! - Alex A.
1
@AlexA。这个包是完全用C++编写的。对于矩阵非常高效。在这种情况下,它只是一种替代方法。 - David Arenburg
@David,太好了!但是当我有多个ID列时,我该如何修改你的脚本? - Sharath
2
@Sharath,简单明了。例如 indx <- !grepl("ID", names(df)) ; df[indx] <- lapply(df[indx], function(x) x - median(x, na.rm = TRUE)) - David Arenburg

4
另外一个选择是:
library(dplyr)
 df %>%
     mutate_each(funs(median=.-median(., na.rm=TRUE)), -ID)

很好的建议。如果我有多个ID列,比如ID_A、ID_B、ID_C,那么在mutate_each函数中该怎样使用它们呢? - Sharath
1
@Sharath 在 ?select 中有一些选项,比如 starts_withmatches 等,可以匹配列名并对这些列进行子集操作或删除。 - akrun
2
@Sharath,你可以做像-ID_A:ID_C这样的事情。 - David Arenburg
@David, akrun,非常感谢。现在我已经轻松搞定了。 :-) - Sharath

0

当然可以。

median(df[,]$Point_A, na.rm = TRUE)

其中 df 是数据框,而 df[,] 表示所有行和列。但是,请注意在 $Point_A 之后指定的列。同样的内容也可以用以下符号表示:

median(df[,"Point_A"], na.rm = TRUE)

在这里,df [,“Point_A”] 再次表示列 Point_A 的所有行。


3
df 等同于 df[,]。虽然这是一个良好的开端,但它并不完整,因为你只考虑到单列操作,而没有提到需要从列中减去中位数。如果有多列(如问题所述),你可以对每一列复制这个中位数方法,但随着列数增加,这变得很麻烦并且最终变得不可行。 - Alex A.

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接