R: Как вы вычисляете (процент) совпадающих наблюдений?

#r #dplyr #match #percentage

#r #dplyr #совпадение #процент

Вопрос:

Итак, мой набор данных выглядит следующим образом, а алфавиты являются факторными переменными. Столбцы Pred предназначены для прогнозируемых наблюдений для каждого идентификатора, а реальные столбцы — для реальных наблюдений. Я хочу вычислить общую точность прогнозируемых значений для каждого идентификатора.

 ID  Pred1 Pred2 Pred3 Real1 Real2 Real3
1    A      C     E      A     D    B
2    A      B     D      E     C    C
3    E      C     A      A     B    D
4    D      A     B      B     B    D
5    B      A     C      C     A    B
  

Итак, я хочу изменить столбец с именем ‘score’, который дает вам процент от числа совпадающих наблюдений между столбцами Pred1, 2, 3 и Real1,2, 3.
Меня интересует только нахождение любых значений ‘Pred’ в любом из ‘реальных’ столбцов.
Если Pred1 найден в одном из Real1, Real2 и Real3, то я даю оценку 1/3.
Если Pred1 И Pred2 (не Pred3) оба найдены в любом из столбцов Real1, Real2 и Real3, (*порядок не имеет значения. Значение Pred1 может быть найдено в Real2 или Real3 — где угодно в ‘Реальных’ столбцах), тогда я даю оценку 2/3.
Я надеюсь, что это имеет смысл. Порядок не имеет значения, и меня интересует только нахождение любого из значений ‘Pred’ в любом из ‘Real’ столбцов.
Итак, я хочу что-то вроде приведенного ниже.

 ID  Pred1 Pred2 Pred3 Real1 Real2 Real3  Score
1    A      C     E      A     D    B     1/3
2    A      B     D      E     C    C      0
3    E      C     A      A     B    D     1/3
4    D      A     B      B     E    D     2/3
5    B      A     C      C     A    B      1
  

Я пытаюсь написать функцию и попробовал что-то вроде
ifelse(«Pred1″%в% c(«Real1», «Real2», «Real3»), 1/3 ,0 )) но это не сработало должным образом.. (были сообщения об ошибках с приведением к логическому и т.д., Которые я не знал, как решить)
Итак, я тоже пробую разные вещи, но продолжаю застревать с ошибками…
Кто-нибудь может помочь, пожалуйста? Заранее благодарю вас!

Ответ №1:

Это затрудняет сравнение значений с разными уровнями коэффициентов. Сначала мы можем преобразовать столбцы из коэффициентов в символы.

 df[-1] <- lapply(df[-1], as.character)
  

Узнайте индекс прогнозируемого и реального столбцов, а затем для каждой строки проверьте, сколько прогнозируемых наблюдений присутствует в реальных.

 pred_cols <- grep("^Pred", names(df))
real_cols <- grep("^Real", names(df))

df$Score <- sapply(1:nrow(df), function(x) 
            sum(df[x, pred_cols] %in% df[x, real_cols]))/length(pred_cols)

df
#  ID Pred1 Pred2 Pred3 Real1 Real2 Real3 Score
#1  1     A     C     E     A     D     B  0.33
#2  2     A     B     D     E     C     C  0.00
#3  3     E     C     A     A     B     D  0.33
#4  4     D     A     B     B     B     D  0.67
#5  5     B     A     C     C     A     B  1.00
  

Поскольку это сравнение по строкам, мы также можем использовать apply с MARGIN = 1 использованием той же логики. При таком подходе нам не нужно явно преобразовывать столбцы в символы.

 apply(df, 1, function(x) sum(x[pred_cols] %in% x[real_cols]))/length(pred_cols)
  

Ответ №2:

Одной tidyverse возможностью может быть:

 bind_cols(df %>%
 gather(var, val, -matches("(Real|ID)")) %>%
 select(ID, val), df %>%
 gather(var2, val2, -matches("(Pred|ID)")) %>%
 select(val2)) %>%
 group_by(ID) %>%
 summarise(res = paste0(sum(val %in% val2), "/3")) %>%
 left_join(df, by = c("ID" = "ID"))

     ID res   Pred1 Pred2 Pred3 Real1 Real2 Real3
  <int> <chr> <fct> <fct> <fct> <fct> <fct> <fct>
1     1 1/3   A     C     E     A     D     B    
2     2 0/3   A     B     D     E     C     C    
3     3 1/3   E     C     A     A     B     D    
4     4 2/3   D     A     B     B     B     D    
5     5 3/3   B     A     C     C     A     B 
  

Сначала он отдельно преобразует столбцы широкого формата в длинный, который содержит Pred и Real . Во-вторых, он объединяет два по столбцам. Наконец, он группирует по «ID», суммирует количество совпадающих наблюдений и объединяет его с исходным df.

Или если количество пар не фиксировано равным 3:

 bind_cols(df %>%
 gather(var, val, -matches("(Real|ID)")) %>%
 select(ID, val), df %>%
 gather(var2, val2, -matches("(Pred|ID)")) %>%
 select(val2)) %>%
 add_count(ID) %>%
 group_by(ID) %>%
 summarise(res = paste(sum(val %in% val2), first(n), sep = "/")) %>%
 left_join(df, by = c("ID" = "ID"))
  

Или если вы хотите числовую переменную в качестве результата:

 bind_cols(df %>%
           gather(var, val, -matches("(Real|ID)")) %>%
           select(ID, val), df %>%
           gather(var2, val2, -matches("(Pred|ID)")) %>%
           select(val2)) %>%
 add_count(ID) %>%
 group_by(ID) %>%
 summarise(res = sum(val %in% val2)/first(n)) %>%
 left_join(df, by = c("ID" = "ID"))

     ID   res Pred1 Pred2 Pred3 Real1 Real2 Real3
  <int> <dbl> <fct> <fct> <fct> <fct> <fct> <fct>
1     1 0.333 A     C     E     A     D     B    
2     2 0     A     B     D     E     C     C    
3     3 0.333 E     C     A     A     B     D    
4     4 0.667 D     A     B     B     B     D    
5     5 1     B     A     C     C     A     B