Как вы можете зациклить эту функцию высшего порядка в R?

Этот вопрос относится к ответу, который я получил здесь с милой маленькой функцией от thelatemail. Фрейм данных, который я использую, не оптимален, но это то, что у меня есть, и я просто пытаюсь зациклить эту функцию по всем строкам.

Это мой дф

dput(SO_Example_v1)
structure(list(Type = structure(c(3L, 1L, 2L), .Label = c("Community", 
"Contaminant", "Healthcare"), class = "factor"), hosp1_WoundAssocType = c(464L, 
285L, 24L), hosp1_BloodAssocType = c(73L, 40L, 26L), hosp1_UrineAssocType = c(75L, 
37L, 18L), hosp1_RespAssocType = c(137L, 77L, 2L), hosp1_CathAssocType = c(80L, 
34L, 24L), hosp2_WoundAssocType = c(171L, 115L, 17L), hosp2_BloodAssocType = c(127L, 
62L, 12L), hosp2_UrineAssocType = c(50L, 29L, 6L), hosp2_RespAssocType = c(135L, 
142L, 6L), hosp2_CathAssocType = c(95L, 24L, 12L)), .Names = c("Type", 
"hosp1_WoundAssocType", "hosp1_BloodAssocType", "hosp1_UrineAssocType", 
"hosp1_RespAssocType", "hosp1_CathAssocType", "hosp2_WoundAssocType", 
"hosp2_BloodAssocType", "hosp2_UrineAssocType", "hosp2_RespAssocType", 
"hosp2_CathAssocType"), class = "data.frame", row.names = c(NA, 
-3L))
####################
#what it looks like#
####################
require(dplyr)
df <- tbl_df(SO_Example_v1)
head(df)
         Type hosp1_WoundAssocType hosp1_BloodAssocType hosp1_UrineAssocType
1  Healthcare                  464                   73                   75
2   Community                  285                   40                   37
3 Contaminant                   24                   26                   18
Variables not shown: hosp1_RespAssocType (int), hosp1_CathAssocType (int), hosp2_WoundAssocType
  (int), hosp2_BloodAssocType (int), hosp2_UrineAssocType (int), hosp2_RespAssocType (int),
  hosp2_CathAssocType (int)

У меня есть функция, чтобы выполнить chisq.test по всем категориям в df$Type, В идеале функция должна переключиться на fisher.test() если число ячеек <5, но это отдельная проблема (дополнительные очки брауни для человека, который придумывает, как это сделать).

Это функция, которую я использую, чтобы идти строка за строкой

func <- Map(
  function(x,y) {
    out <- cbind(x,y)
    final <- rbind(out[1,],colSums(out[2:3,]))
    chisq <- chisq.test(final,correct=FALSE)
    chisq$p.value
  },
  SO_Example_v1[grepl("^hosp1",names(SO_Example_v1))],
  SO_Example_v1[grepl("^hosp2",names(SO_Example_v1))] 
)
func

Но в идеале я бы хотел, чтобы это было что-то вроде этого

for(i in 1:nrow(df)){func}

Но это не работает. Еще один прием заключается в том, что когда, например, берется второй ряд, final звонок выглядит так

func <- Map(
  function(x,y) {
    out <- cbind(x,y)
    final <- rbind(out[2,],colSums(out[c(1,3),]))
    chisq <- chisq.test(final,correct=FALSE)
    chisq$p.value
  },
  SO_Example_v1[grepl("^hosp1",names(SO_Example_v1))],
  SO_Example_v1[grepl("^hosp2",names(SO_Example_v1))] 
)
func

поэтому функция должна понимать, что число клеток out[x,] должен быть исключен из colSums(), это data.frame только 3 строки, так что это легко, но я попытался применить эту функцию к отдельному data.frame, который у меня есть>200 строк, поэтому было бы неплохо иметь возможность как-то зацикливать это.

Любая помощь приветствуется.

ура

1 ответ

Решение

Вам не хватало двух вещей:

  1. Чтобы выбрать строку i и выбрать все, кроме этой строки, которую вы хотите использовать u[i] а также u[-i]
  2. Если элемент не такой длины, как другие, заданные для Map, он используется повторно, что является очень общим свойством языка. Затем вам просто нужно добавить в функцию аргумент, соответствующий строке, которую вы хотите противопоставить другим, и она будет переработана для всех элементов переданных векторов.

Следующее делает то, что вы просили

    # the function doing the stats
    FisherOrChisq <- function(x,y,lineComp) {
        out <- cbind(x,y)
        final <- rbind(out[lineComp,],colSums(out[-lineComp,]))
        test <- chisq.test(final,correct=FALSE)

        return(test$p.value)
    }

    # test of the stat function
    FisherOrChisq(SO_Example_v1[grep("^hosp1",names(SO_Example_v1))[1]],
    SO_Example_v1[grep("^hosp2",names(SO_Example_v1))[1]],2)

    # making the loop
    result <- c()
    for(type in SO_Example_v1$Type){
        line <- which(SO_Example_v1$Type==type)
        res <- Map(FisherOrChisq,
                    SO_Example_v1[grepl("^hosp1",names(SO_Example_v1))],
                    SO_Example_v1[grepl("^hosp2",names(SO_Example_v1))],
                    line
                )
        result <- rbind(result,res)
    }
    colnames(result) <- gsub("^hosp[0-9]+","",colnames(result))
    rownames(result) <- SO_Example_v1$Type

Тем не менее, то, что вы делаете, это очень тяжелое многократное тестирование. Я был бы очень осторожен с использованием соответствующих значений p, вам нужно, по крайней мере, использовать множественную коррекцию тестирования, такую ​​как предложенная здесь.

Другие вопросы по тегам