Как правильно сделать wilcox.test для нескольких столбцов с NA в R? - PullRequest
0 голосов
/ 06 апреля 2020

Я пытаюсь сделать wilcox.test для нескольких столбцов против целевого столбца, где каждый столбец имеет значения NA, и мне нужно отбросить его для каждого столбца независимо. Чтобы сделать wilcox.test, сначала мне нужно сделать выборку для каждого столбца, затем сбросить NA в текущих столбцах, затем отфильтровать значение целевого столбца, но мне не удается получить индекс NA в текущем столбце, потому что я использовал which(is.na(df$x1), arr.ind=TRUE), но это не поможет мне, как сохранить соответствующие значения в целевом столбце. Поскольку позиция NA в каждом столбце различна, соответствующие значения целевого столбца также изменяются. Я не знаю, как делать подобные манипуляции в R. Может ли кто-нибудь указать мне, как это сделать? любая мысль?

воспроизводимый пример :

вот минимальные воспроизводимые данные для моей задачи:

> dput(mydf)
structure(list(v1 = c(3.69055560203349, 3.01675043088942, 3.4195128033004, 
NA, 3.5798210897553, 4.00279762977148, 3.39364072476593, 3.74902908274812, 
3.75245019598874, NA), v2 = c(8.29251175276882, 6.03085239544148, 
6.61202305724909, 6.32182430455213, 7.01468228541546, 7.91002666664165, 
8.43386943449607, 8.5247956890294, 8.052886597559, 7.22851794548592
), v3 = c(2.67156354473232, 2.36125329858185, 2.17487388876694, 
NA, 2.17995780295262, 2.0439205043448, 1.71779360521063, 2.02967258021284, 
2.04390173884486, NA), v4 = c(2.9771612602651, 2.8554942149399, 
2.86921526382523, NA, 3.5642547915086, 3.02900788965761, 2.86324542975628, 
2.8451951395453, 2.17256320516553, NA), label = c(0L, 1L, 0L, 
1L, 0L, 1L, 0L, 0L, 1L, 0L)), class = "data.frame", row.names = c(NA, 
10L))

моя попытка:

Я хочу сделать выборку для каждого столбца, затем найти соответствующее значение целевого столбца, затем сделать wilcox.test. Вот что я попробовал:

label = mydf$label
lapply(1:5, function(i){
    res= lapply(colnames(mydf), function(x){
        col_rmna = na.omit(mydf[x])
        sample_size = floor(0.33*nrow(col_rmna))
        split_index <- sample(seq_len(nrow(col_rmna)), size = sample_size, replace = FALSE)
        feat_samped = col_rmna[split_index, ]
        label = subset(label, feat_samped[!which(is.na(feat_samped), arr.ind=TRUE),])
        wtst = wilcox.test(feat_samped ~label)$p.value
    })
    ## put the output of each itertion into list 
})

, но я не знаю, как получить соответствующее значение lable и сделать wilcox.test для каждого столбца выборки с соответствующим значением метки. Моя конечная цель состоит в том, чтобы вычислить среднее значение p для каждого столбца после нескольких итераций, в которых генерируются различные значения выборочных столбцов.

Может кто-нибудь указать мне, как сделать это последовательным? как искать и сохранять значения целевого столбца, просматривая значения NA в другом столбце, где значения, появившиеся в строке NA, просто отбрасываются? Есть идеи?

цель :

Здесь я хочу запустить несколько итераций, где делать выборку для каждого столбца и делать wilcox.test, конечный результат будет кадром данных, где среднее p -значение каждого столбца должно быть включено. как это сделать? Есть ли более простой способ сделать такую ​​задачу в R? спасибо

1 Ответ

3 голосов
/ 06 апреля 2020

Я не оцениваю обоснованность этого подхода, только его программную c реализацию.

Мы можем использовать which() для преобразования логического вектора, наблюдения которого не равны NA, и вместо выборки данных напрямую, выборка индексов. Таким образом, индексы также будут соответствовать положению меток. Я также позаботился о случае, когда выбирается только одна из двух меток, так как это создаст только один фактор, и wilcox.test потерпит неудачу.

sample.fraction <- 0.8
trials <- 10
result <- lapply(mydf[,1:4],function(x){
  pvals <- vector();
  for(i in seq(1,trials)){
    number.non.na.obs <- length(x[!is.na(x)]);
    n.sample <- floor(sample.fraction*number.non.na.obs);
    logical.not.na <- !is.na(x);
    target.indices <- which(logical.not.na);
    sample <- sample(target.indices,n.sample);
    n.labels.sampled <- length(table(mydf$label[sample]));
    if(n.labels.sampled < 2){pvals[i] <- NA}
     else{pvals[i] <- wilcox.test(x[sample]~mydf$label[sample])$p.value}
  }
return(pvals);  
})
result
#$v1
# [1] 0.3333333 1.0000000 0.7000000 0.7000000 0.1333333 1.0000000 1.0000000 1.0000000 1.0000000 0.3333333
#$v2
# [1] 0.1142857 0.4285714 0.3428571 0.4285714 0.1142857 0.1142857 0.1428571 0.2500000 0.1428571 0.3428571
#$v3
# [1] 0.5333333 1.0000000 0.5333333 0.5333333 0.6666667 0.5333333 0.5333333 1.0000000 1.0000000 0.8000000
#$v4
# [1] 1.0000000 0.2666667 0.6666667 0.8000000 0.8000000 1.0000000 0.2666667 0.3333333 0.4000000 1.0000000

Если вы хотите получить среднее значение, вы можете использовать sapply.

sapply(result, mean)
#       v1        v2        v3        v4 
#0.5533333 0.3321429 0.7166667 0.6933333 

Данные

mydf <- structure(list(v1 = c(3.69055560203349, 3.01675043088942, 3.4195128033004, 
NA, 3.5798210897553, 4.00279762977148, 3.39364072476593, 3.74902908274812, 
3.75245019598874, NA), v2 = c(8.29251175276882, 6.03085239544148, 
6.61202305724909, 6.32182430455213, 7.01468228541546, 7.91002666664165, 
8.43386943449607, 8.5247956890294, 8.052886597559, 7.22851794548592
), v3 = c(2.67156354473232, 2.36125329858185, 2.17487388876694, 
NA, 2.17995780295262, 2.0439205043448, 1.71779360521063, 2.02967258021284, 
2.04390173884486, NA), v4 = c(2.9771612602651, 2.8554942149399, 
2.86921526382523, NA, 3.5642547915086, 3.02900788965761, 2.86324542975628, 
2.8451951395453, 2.17256320516553, NA), label = c(0L, 1L, 0L, 
1L, 0L, 1L, 0L, 0L, 1L, 0L)), class = "data.frame", row.names = c(NA, 
10L))
...