Р: Как вы рассчитываете (процент) совпадающих наблюдений? - PullRequest
0 голосов
/ 16 марта 2019

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

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» в любом из столбцов «Real».Если Pred1 найден в одном из Real1, Real2 и Real3, то я даю оценку 1/3.Если Pred1 и Pred2 (не Pred3) оба найдены в любом из столбцов Real1, Real2 и Real3, (* порядок НЕ имеет значения. Pred1 можно найти в Real2 или Real3 - только в любом месте столбцов 'Real'), тогда я даюоценка 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))но это не сработало ... (были сообщения об ошибках с принуждением к логическому и т. д., которые я не знал, как решить). Поэтому я тоже пробую разные вещи, но продолжаю зацикливаться на ошибках ... Кто-нибудь может помочь, пожалуйста?Заранее спасибо!

Ответы [ 2 ]

2 голосов
/ 16 марта 2019

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

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

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

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)
1 голос
/ 16 марта 2019

Одна 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 
...