1

这应该是一个基本问题,可能有重复,但我似乎找不到它们,所以请多多包涵并指出正确的地方。谢谢!

我有一个数据框,其中包含可能存在 NA 和缺失值的整数。我正在计算行平均值(将 NA 设置为零)和列平均值(跳过 NA)。然后我想创建一个数据框(或表),其中包含整数以及行平均值和列平均值。这是一个示例数据框:

df <- data.frame(
  'ID' = c("123A","456B","789C","1011","1213")
  , 'Test 1' = c(55,65,60,NA,50)
  , 'Test 2' = c(45,48,50,52,55)
  , 'Test 3' = c(51,49,55,69,61)
 )
df
    ID Test.1 Test.2 Test.3
1 123A     55     45     51
2 456B     65     48     49
3 789C     60     50     55
4 1011     NA     52     69
5 1213     50     55     61

这是计算列的函数,即跳过 NA:

colMean <- function(df, na.rm = TRUE) {
  if (na.rm) {
    n <- rowSums(!is.na(df))
  } else {
    n <- ncol(df)
  }
  colMean <- colMeans(df, na.rm=na.rm)
  return(rbind(df, "colMean" = colMean))
}

这是计算行意味着将 NA 设置为零的函数:

rowMeanz <- function(df) {
  df[is.na(df)] <- 0
  return(cbind(df, "rowMean" = rowMeans(df)))
}

一个问题是 rbind 改变了数据类型,因为整数在标记为“Test.1”的列中转换为浮点数(或看起来是):

colMean(df[sapply(df, is.numeric)])
        Test.1 Test.2 Test.3
1         55.0     45     51
2         65.0     48     49
3         60.0     50     55
4           NA     52     69
5         50.0     55     61
colMean   57.5     50     57

在您的回答中,我非常感谢您解释为什么在这种情况下似乎只有第一列受到影响。是否与列中存在 NA 有关?

基于 cbind,我没有观察到其他函数存在同样的问题:

rowMeanz(df[sapply(df, is.numeric)])
  Test.1 Test.2 Test.3  rowMean
1     55     45     51 50.33333
2     65     48     49 54.00000
3     60     50     55 55.00000
4      0     52     69 40.33333
5     50     55     61 55.33333

最终我想获得一个看起来像这样的数据框或表:

    ID Test.1 Test.2 Test.3  rowMean
1 123A     55     45     51 50.33333
2 456B     65     48     49 54.00000
3 789C     60     50     55 55.00000
4 1011     NA     52     69 40.33333
5 1213     50     55     61 55.33333
6 colMean  57.5   50     57 

如果您能以不多的步骤向我展示如何做到这一点,我将不胜感激。我对基本 R 答案以及基于包的答案持开放态度。这些计算将在闪亮的应用程序中在线完成,所以我特别希望看到有效的方法。非常感谢!

4

3 回答 3

1

不确定我的解决方案是否对您的问题特别有帮助,但以下是我的方法:

df <- data.frame(
  'Test 1' = c(55,65,60,NA,50),
  'Test 2' = c(45,48,50,52,55),
  'Test 3' = c(51,49,55,69,61)
)

#First, it might be a good idea to set the id as the rownames.
rownames(df) <- c("123A","456B","789C","1011","1213")

#Calculate the col and row means
colMean <- apply(df, 2, function(x) mean(x, na.rm = T))
df$rowMean <- apply(df, 1, function(x) mean(x, na.rm = T))
df <- rbind(df, colMeans)
rownames(df)[nrow(df)] <- "colMean"
于 2013-11-25T20:12:02.937 回答
1

最好以所需的方式将数据转换为字符格式,然后将各个部分放在一起。

df <- data.frame(
  row.names = c("123A","456B","789C","1011","1213")
  , 'Test 1' = c(55,65,60,NA,50)
  , 'Test 2' = c(45,48,50,52,55)
  , 'Test 3' = c(51,49,55,69,61)
 )

colm <- colMeans(df, na.rm=TRUE)
d0 <- df
d0[is.na(d0)] <- 0
rowm <- rowMeans(d0)

dd <- format(df)
dc <- formatC(colm, digits=1, format="f")
dr <- formatC(rowm, digits=4, format="f")
out <- cbind(rbind(dd, colMeans=dc), rowMeans=c(dr, ""))
print(out, right=FALSE)

##          Test.1 Test.2 Test.3 rowMeans
## 123A     55     45     51     50.3333 
## 456B     65     48     49     54.0000 
## 789C     60     50     55     55.0000 
## 1011     NA     52     69     40.3333 
## 1213     50     55     61     55.3333 
## colMeans 57.5   50.0   57.0      
于 2013-11-25T20:35:42.947 回答
0

我想跟进我如何使用 Aaron 的建议来生成一个汇总数据的表格。它应该很容易扩展到其他统计数据,例如最小值、最大值、偏差等。

数据:

df <- data.frame(
    'ID' = c("123A","456B","789C","1011","1213")
    , 'Test 1' = c(13,8,14,NA,15)
    , 'Test 2' = c(13,4,16,7,12)
    , 'Test 3' = c(15,9,13,6,13)
)

计算用于汇总数据的统计数据的几个函数:

colMean <- function(df, na.rm = TRUE) {# either remove or annull NAs
  if (!na.rm) {# annull NAs
    df[is.na(df)] <- 0
  }
  colMean <- colMeans(df, na.rm=na.rm)
  return(colMean)
}
rowMean <- function(df, na.rm = TRUE) {# either remove or annull NAs
  if (!na.rm) {# annull NAs
    df[is.na(df)] <- 0
  }
  rowMean <- rowMeans(df, na.rm=na.rm)
  return(rowMean)
}
rowSd <- function(df, na.rm = TRUE) {# either remove or annull NAs
  if (na.rm) {# remove NAs
    n <- rowSums(!is.na(df))
  } else {
    df[is.na(df)] <- 0
    n <- ncol(df)
  }
  rowMean <- rowMeans(df, na.rm=na.rm)
  rowVar <- rowMeans(df*df, na.rm=na.rm) - (rowMeans(df, na.rm=na.rm))^2
  rowSd <- sqrt(rowVar * n/(n-1))
  return(rowSd)
}
colSd <- function(df, na.rm = TRUE) {# either remove or annull NAs
  if (na.rm) {# remove NAs
    n <- colSums(!is.na(df))
  } else {
    df[is.na(df)] <- 0
    n <- nrow(df)
  }
  colMean <- colMeans(df, na.rm=na.rm)
  colVar <- colMeans(df*df, na.rm=na.rm) - (colMeans(df, na.rm=na.rm))^2
  colSd <- sqrt(colVar * n/(n-1))
  return(colSd)
}

作为数据框“df”、沿列统计信息“col”、沿行“统计信息”和填充字符“pad”的函数的摘要。'pad' 字符可以设置为带有“”的空单元格或设置为 NA 或其他内容。默认情况下,NA 沿列删除,但默认情况下沿行设置为零。

summ <- function(df
  , col = list("colMean" = colMean)
  , row = list("rowMean" = rowMean)
  , pad = NA_character_)
{
  dfN <- df[sapply(df, is.numeric)]
  colN <-lapply(col, function(x){formatC(x(dfN, na.rm = TRUE), 'digits' = 1, 'format' = "f")})
  rowN <-lapply(row, function(x){formatC(x(dfN, na.rm = FALSE), 'digits' = 1, 'format' = "f")})
  pad <- rep(pad,'length' = length(colN))
  out <- cbind(rbind(format(dfN),do.call(rbind,colN)), lapply(rowN,function(x){c(x,pad)}))
  return(print(out, 'right' = FALSE))
}

使用示例:

c <- list("colMean" = colMean, "colSd" = colSd)
r <- list("rowMean" = rowMean, "rowSd" = rowSd)
summ(df)
summ(df,c,r)
summ(df,'col'=c,'row'=r)
summ(df,'col'=c,'row'=r, 'pad'="X")
        Test.1 Test.2 Test.3 rowMean rowSd
1       13     13     15     13.7    1.2
2        8      4      9     7.0     2.6
3       14     16     13     14.3    1.5
4       NA      7      6     4.3     3.8
5       15     12     13     13.3    1.5
colMean 12.5   10.4   11.2   X       X
colSd   3.1    4.8    3.6    X       X

当然,请随时发表评论。谢谢!

于 2013-11-27T09:09:58.123 回答