簡體   English   中英

用R中的條件計算乘列的均值

[英]Calculate Mean of Multiply Columns with Condition in R

我想計算多個變量的均值,但在有條件的情況下,如果這些列中的2個均具有NA,則均值將為NA,如果小於2,則找到均值

df <- data.frame(ID = c(1:10),X1 = c(rep(1,5),rep(2,5)),X2 = c(1:10),X3 =   c(1,NA,2,NA,NA,1,NA,2,NA,NA),X4 = c(rep(NA,10)),X5=c(rep(1,5),rep(NA,5)),
             Y1 = c(rep(1,5),rep(2,5)),Y2 = c(1:10),Y3 = c(1,NA,2,NA,NA,1,NA,2,NA,NA),Y4 = c(rep(NA,10)),Y5=c(rep(1,5),rep(NA,5)))

MeanX = round(apply(df[,c(2:6)],1, mean,na.rm = TRUE),2)
MeanY = round(apply(df[,c(7:11)],1,mean,na.rm = TRUE),2)

這是輸出不正確

   ID X1 X2 X3 X4 X5 Y1 Y2 Y3 Y4 Y5 MeanX MeanY
1   1  1  1  1 NA  1  1  1  1 NA  1  1.00  1.00
2   2  1  2 NA NA  1  1  2 NA NA  1  1.33  1.33*
3   3  1  3  2 NA  1  1  3  2 NA  1  1.75  1.75
4   4  1  4 NA NA  1  1  4 NA NA  1  2.00  2.00*
5   5  1  5 NA NA  1  1  5 NA NA  1  2.33  2.33*
6   6  2  6  1 NA NA  2  6  1 NA NA  3.00  3.00*
7   7  2  7 NA NA NA  2  7 NA NA NA  4.50  4.50 *
8   8  2  8  2 NA NA  2  8  2 NA NA  4.00  4.00 *
9   9  2  9 NA NA NA  2  9 NA NA NA  5.50  5.50 *
10 10  2 10 NA NA NA  2 10 NA NA NA  6.00  6.00 * This is supposed NA,bc there are 3 columns have NA

因為我有一個很大的數據集,所以有時每組必須設置20個中的6個,有時需要設置10個中的1個,因此我可以計算均值,以及如何為這種情況設置條件。

這是一個非常快速(必須運行)且帶有data.table骯臟解決方案。 但我相信可以對其進行清理和構建,以使它們變得整潔且效果良好。

# Load data.table
require(data.table)
setDT(df)

# Format all columns as as numeric, 
# otherwise mean is not meaningful (see what I did there?)
x.cols <- paste("X", 1:5, sep = "")
y.cols <- paste("Y", 1:5, sep = "")
setDT(df)[, (x.cols) := lapply(.SD, as.integer), .SDcols = x.cols]
setDT(df)[, (y.cols) := lapply(.SD, as.integer), .SDcols = y.cols]

# meanX first mean, and then NA
df[, meanX := mean(c(X1, X2, X3, X4, X5), na.rm = TRUE), by =ID]
df[df[, sum(is.na(c(X1, X2, X3, X4, X5))) > 2, by = ID]$V1, meanX := NA]

# meanY first mean, and then NA
df[, meanY := mean(c(Y1, Y2, Y3, Y4, Y5), na.rm = TRUE), by =ID]
df[df[, sum(is.na(c(Y1, Y2, Y3, Y4, Y5))) > 2, by = ID]$V1, meanY := NA]

# Result
df

    ID X1 X2 X3 X4 X5 Y1 Y2 Y3 Y4 Y5    meanX    meanY
 1:  1  1  1  1 NA  1  1  1  1 NA  1 1.000000 1.000000
 2:  2  1  2 NA NA  1  1  2 NA NA  1 1.333333 1.333333
 3:  3  1  3  2 NA  1  1  3  2 NA  1 1.750000 1.750000
 4:  4  1  4 NA NA  1  1  4 NA NA  1 2.000000 2.000000
 5:  5  1  5 NA NA  1  1  5 NA NA  1 2.333333 2.333333
 6:  6  2  6  1 NA NA  2  6  1 NA NA 3.000000 3.000000
 7:  7  2  7 NA NA NA  2  7 NA NA NA       NA       NA
 8:  8  2  8  2 NA NA  2  8  2 NA NA 4.000000 4.000000
 9:  9  2  9 NA NA NA  2  9 NA NA NA       NA       NA
10: 10  2 10 NA NA NA  2 10 NA NA NA       NA       NA

這是基本的R解決方案。

我認為,如果您先使用長格式,則從概念上講比較容易,例如:

long <- reshape(df, idvar='ID', varying=colnames(df)[-1], timevar='t', sep='', direction='long')

這將變量下標移動到變量t 它看起來像這樣:

> str(long)
'data.frame':   50 obs. of  4 variables:
 $ ID: int  1 2 3 4 5 6 7 8 9 10 ...
 $ t : num  1 1 1 1 1 1 1 1 1 1 ...
 $ X : num  1 1 1 1 1 2 2 2 2 2 ...
 $ Y : num  1 1 1 1 1 2 2 2 2 2 ...
 - attr(*, "reshapeLong")=List of 4
  ..$ varying:List of 2
  .. ..$ X: chr  "X1" "X2" "X3" "X4" ...
  .. ..$ Y: chr  "Y1" "Y2" "Y3" "Y4" ...
  .. ..- attr(*, "v.names")= chr  "X" "Y"
  .. ..- attr(*, "times")= num  1 2 3 4 5
  ..$ v.names: chr  "X" "Y"
  ..$ idvar  : chr "ID"
  ..$ timevar: chr "t"

然后,您可以根據自己的描述自然地編寫一個聚合函數。 這與@snoram匹配:

f <- function(x) if( sum(is.na(x)) > 2 ) NA else mean(x, na.rm=TRUE)

請注意, aggregate的默認行為是跳過NA,但是您可以更改該選項:

aggregate(cbind(meanx=X,meany=Y)~ID, long, f, na.action=na.pass)

這使:

   ID       meanx       meany
1   1 1.000000000 1.000000000
2   2 1.333333333 1.333333333
3   3 1.750000000 1.750000000
4   4 2.000000000 2.000000000
5   5 2.333333333 2.333333333
6   6 3.000000000 3.000000000
7   7          NA          NA
8   8 4.000000000 4.000000000
9   9          NA          NA
10 10          NA          NA

然后,您可以根據需要將其cbind回原始數據框。

這種方法的優點是,如果您還擁有X6,X7等,則應該輕松應對。

編輯:

重新閱讀您的問題,最好分別跟蹤NA的平均值和數量,然后再進行處理。 這是一個快速而骯臟的例子:

>     f <- function(x) c(sum(is.na(x)), mean(x, na.rm=TRUE))
> agg <-    aggregate(cbind(meanx=X,meany=Y)~ID, long, f, simplify=FALSE, na.action=na.pass);
> agg
   ID                    meanx                    meany
1   1                     1, 1                     1, 1
2   2 2.000000000, 1.333333333 2.000000000, 1.333333333
3   3               1.00, 1.75               1.00, 1.75
4   4                     2, 2                     2, 2
5   5 2.000000000, 2.333333333 2.000000000, 2.333333333
6   6                     2, 3                     2, 3
7   7                 3.0, 4.5                 3.0, 4.5
8   8                     2, 4                     2, 4
9   9                 3.0, 5.5                 3.0, 5.5
10 10                     3, 6                     3, 6
> g <- function(x, i) if(x[1] <= i) x[2] else NA
> mapply(lapply, agg[2:3],list(g), c(2,1))
   meanx       meany
01 1           1    
02 1.333333333 NA   
03 1.75        1.75 
04 2           NA   
05 2.333333333 NA   
06 3           NA   
07 NA          NA   
08 4           NA   
09 NA          NA   
10 NA          NA   

這樣,您可以為不同的列指定不同數量的NA。 嵌套的道歉適用。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM