Search code examples
rfunctiondplyricc

Using dplyr to create a ICCs table


I am trying to create a table with ICCs for multiple raters and multiple variables, I am trying to use a function and dplyr, but it is not working as I expected.

This is the structure of the data frame and the expected ICCs table:

# Create data frame
ID <- c("r1", "r1", "r1", "r1", "r1", "r2", "r2", "r2", "r2", "r2", "r3", "r3", "r3", "r3", "r3")
V1.1 <- c(3, 3, 3, 3, 3, 3, 2, 3, 3, 1, 2, 2, 1, 1, 2)
V2.1 <- c(1, 1, 2, 1, 2, 1, 1, 1, 2, 1, 1, 2, 1, 1, 3)
V3.1 <- c(1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1)
V4.1 <- c(2, 2, 2, 1, 2, 2, 2, 2, 2, 1, 2, 2, 1, 1, 2)
V1.2 <- c(3, 3, 3, 3, 3, 3, 2, 3, 2, 2, 3, 2, 1, 2, 1)
V2.2 <- c(1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 2, 2)
V3.2 <- c(1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1)
V4.2 <- c(2, 4, 2, 1, 3, 2, 1, 3, 2, 2, 3, 2, 1, 2, 1)

df <- data.frame(ID, V1.1, V2.1, V3.1, V4.1, V1.2, V2.2, V3.2, V4.2)

# Empty data frame for ICCs
ids <- c("r1", "r2", "r3")
vars <- c("V1", "V2", "V3", "V4")

icc_table <- data.frame(ID = ids)
icc_table <- cbind(icc_table, matrix(NA, nrow = length(ids), ncol = length(vars)))
names(icc_table)[2:ncol(icc_table)] <- vars

Here is the attempt to create the ICCs table with a function and dplyr:

# ICC function
icc.fun <- function(data, x1, x2){
    result <- irr::icc(subset(data, select = c(x1, x2)), 
                  model = "twoway",
                  type = "agreement",
                  unit = "single")
    result$value
}

# Table attempt
icc_table <- df %>%
    pivot_longer(cols = -ID, names_to = c("criteria", ".value"), names_pattern = "(V\\d)\\.(\\d)") %>% 
    group_by(ID, criteria) %>% 
    rename("val1" = `1`, "val2" = `2`) %>%
    summarise(icc = icc.fun(df, val1, val2), .groups = "drop") %>% 
    pivot_wider(id_cols = ID, names_from = criteria, values_from = icc)

However, it is not working and it returns a table with a lot of NAs. When I tried the function it seems to be working fine, so I guess it is a problem with the dplyr code. If you have any other solution apart from dplyr it is also welcomed!

Thanks!


Solution

  • In case it is useful for someone, here is the solution that I found:

    1. I simplified the function by subsetting the data using R base
    # ICC function
    icc.fun <- function(data, x1, x2){
        result <- icc(data[ ,c(x1, x2)], 
                  model = "twoway",
                  type = "agreement",
                  unit = "single")
        result$value
    }
    
    1. I used the group_modify() instead of summarise(), plus enframe()
    # Create ICC table
        icc_table <- df %>%
        pivot_longer(cols = -ID, names_to = c("criteria", ".value"), names_pattern = "(V\\d)\\.(\\d)") %>% 
        group_by(ID, criteria) %>% 
        rename("val1" = `1`, "val2" = `2`) %>%
        group_modify(~ {
            icc.fun(.x, "val1", "val2") %>%
        tibble::enframe(name = "variable", value = "icc")
            }) %>%
        pivot_wider(id_cols = ID, names_from = criteria, values_from = icc)