R:你如何计算匹配观测值(百分比)?

问题描述 投票:0回答:2

所以我的数据集看起来像这样,字母表是因子变量。 Pred列用于每个ID的预测观察,Real列是真实的观察。我想计算每个ID的预测值的总体准确性。

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列之间匹配观察数量的百分比。我只关心在'Real'列中找到任何'Pred'值。如果在Real1,Real2和Real3中找到Pred1,那么我给出1/3的分数。如果Pred1和Pred2(不是Pred3)都在Real1,Real2和Real3列中找到,(*顺序无关紧要。可以在Real2或Real3中找到Pred1-就在'Real'列中的任何位置),然后我给出得分为2/3。我希望这是有道理的。顺序无关紧要,我只关心在'Real'列中查找任何'Pred'值。所以我想要下面这样的东西。

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(“%1”中的“Pred1”%(“Real1”,“Real2”,“Real3”),1/3,0))但是效果不好... (有强制到逻辑等的错误消息,我不知道如何解决)所以我也在尝试不同的东西,但仍然遇到错误......任何人都可以帮忙吗?先感谢您!

r dplyr match percentage
2个回答
2
投票

这使得难以比较具有不同因子水平的值。我们可以先将列从因子转换为字符。

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

找出Predicted和Real列的索引,然后针对每一行检查Real中存在多少个Predicted观察值。

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

由于它是行式比较,我们也可以使用applyMARGIN = 1使用相同的逻辑。使用这种方法,我们不需要将列显式转换为字符。

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

1
投票

一个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 

首先,分别将包含PredReal的列从宽格式转换为长格式。其次,它将两个列组合在一起。最后,按“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 
© www.soinside.com 2019 - 2024. All rights reserved.