简体   繁体   中英

Take Symmetrical Mean of a tibble (ignoring the NAs)

I have a tibble where the rows and columns are the same IDs and I would like to take the mean (ignoring the NAs) to make the df symmetrical. I am struggling to see how.

data <- tibble(group = LETTERS[1:4], 
               A = c(NA, 10, 20, NA),
               B = c(15, NA, 25, 30),
               C = c(20, NA, NA, 10),
               D = c(10, 12, 15, NA)
               )

I would normally do

A <- as.matrix(data[-1])
(A + t(A))/2

But this does not work because of the NAs.

Edit: below is the expected output.

output <- tibble(group = LETTERS[1:4],
                 A = c(NA, 12.5, 20, 10),
                 B = c(12.5, NA, 25, 21),
                 C = c(20, 25, NA, 12.5),
                 D = c(10, 21, 12.5, NA))

Here is a suggestion using tidyverse code.

library(tidyverse)

data <- tibble(group = LETTERS[1:4], 
               A = c(NA, 10, 20, NA),
               B = c(15, NA, 25, 30),
               C = c(20, NA, NA, 10),
               D = c(10, 12, 15, NA)
)

A <- data %>% 
  pivot_longer(-group, values_to = "x")

B <- t(data) %>% 
  as.data.frame() %>% 
  setNames(LETTERS[1:4]) %>% 
  rownames_to_column("group") %>% 
  pivot_longer(-group, values_to = "y") %>% 
  left_join(A, by = c("group", "name")) %>% 
  mutate(
    mean = if_else(!(is.na(x) | is.na(y)), (x + y)/2, x),
    mean = if_else(is.na(mean) & !is.na(y), y, mean)
    ) %>% 
  select(-x, -y) %>% 
  pivot_wider(names_from = name, values_from = mean)

B

## A tibble: 4 x 5
#  group     A     B     C     D
#  <chr> <dbl> <dbl> <dbl> <dbl>
#1 A      NA    12.5  20    10  
#2 B      12.5  NA    25    21  
#3 C      20    25    NA    12.5
#4 D      10    21    12.5  NA  

Okay so this is how I ended up doing this. I would have preferred if I didnt use a for loop because the actual data I have is much bigger but beggars cant be choosers!

A <- as.matrix(data[-1])

for (i in 1:nrow(A)){
  for (j in 1:ncol(A)){
    if(is.na(A[i,j])){
      A[i,j] <- A[j, i]
    }
  }
}

output <- (A + t(A))/2
output %>% 
  as_tibble() %>% 
  mutate(group = data$group) %>% 
  select(group, everything())

# A tibble: 4 x 5
  group     A     B     C     D
  <chr> <dbl> <dbl> <dbl> <dbl>
1 A      NA    12.5  20    10  
2 B      12.5  NA    25    21  
3 C      20    25    NA    12.5
4 D      10    21    12.5  NA 

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM