我有一个由几列已知/预期结果组成的data.frame,并希望将它们与结构相同但结果可能不同的第二个data.frame进行比较。有四种可能的情况:
我想生成一个新的data.frame,它对已知/观察到的data.frames中的每一列都评估这四个条件
我遇到过描述向量中多个条件的帖子,但是我没有看到任何有关比较两个共享相同索引(在R中)的向量元素的信息。
为了简单起见,我们有一对地图:“真实”地图是我们期望的,而“观察”地图是我们记录的。对于这两个地图,这些观测值都发生在相同的位置,并且每个位置都分为三部分(国家,地区和区域)。
true_map <- data.frame(
MapSection = paste0("mapsection", seq(1:5)),
Country = c(rep("Canada", 3), rep("UnitedStates", 2)),
Region = c(rep("Ontario", 3), "NewYork", "Alaska"),
Zone = c("Toronto", "Ottawa", NA, "Albany", NA)
)
obsrvd_map <- data.frame(
MapSection = paste0("mapsection", seq(1:5)),
Country = c(rep("Canada", 3), rep("UnitedStates", 2)),
Region = c(rep("Ontario", 2), NA, "NewYork", "Alaska"),
Zone = c("Toronto", "Ottawa", NA, "Albany", "Fairbanks")
)
在Country
级别,真实地图和观察到的地图是相同的。但是,在Region
级别,mapsection3在“已观察”地图(NA
)中缺少信息,而“ true”地图具有位置(Ontario
)。这将被归类为FalseNegative,因为我们缺少期望的信息。
相反,mapsection5在Zone
级别的“ true”映射中缺少信息,而“ observed”映射包含信息(Fairbanks
)。这将被归类为FalsePositive,因为在我们不希望获得信息的地方还有其他信息。但是,“真实”和“观察”地图在mapsection3的Zone
级别都缺少信息。这将被视为TrueNegative,因为两者都缺少信息。
最终结果将这些观察总结如下:
MapSection Country Region Zone
mapsection1 TP TP TP
mapsection2 TP TP TP
mapsection3 TP FN TN
mapsection4 TP TP TP
mapsection5 TP TP FP
谢谢您的协助!
答案 0 :(得分:1)
您的答案中的逻辑看起来很扎实,但还没有扩展到您需要的其他组合。为此,我将数据重整为长格式,以便您有一列地理级别和一个区域。
library(dplyr)
library(tidyr)
true_map_long <- true_map %>%
gather(key = level, value = value, -MapSection)
obsrvd_map_long <- obsrvd_map %>%
gather(key = level, value = value, -MapSection)
两者的形状如下:
head(true_map_long)
#> MapSection level value
#> 1 mapsection1 Country Canada
#> 2 mapsection2 Country Canada
#> 3 mapsection3 Country Canada
#> 4 mapsection4 Country UnitedStates
#> 5 mapsection5 Country UnitedStates
#> 6 mapsection1 Region Ontario
按地图部分和级别加入这两个长形表,并提供适当的后缀以使其更清楚。 case_when
本质上是相同的,但是现在您不再局限于一个位置。
joined <- inner_join(
true_map_long,
obsrvd_map_long,
by = c("MapSection", "level"),
suffix = c("_t", "_o")
) %>%
mutate(truth = case_when(
value_t == value_o ~ "TP",
is.na(value_t) == is.na(value_o) ~ "TN",
is.na(value_t) & !is.na(value_o) ~ "FP",
!is.na(value_t) & is.na(value_o) ~ "FN",
))
head(joined)
#> MapSection level value_t value_o truth
#> 1 mapsection1 Country Canada Canada TP
#> 2 mapsection2 Country Canada Canada TP
#> 3 mapsection3 Country Canada Canada TP
#> 4 mapsection4 Country UnitedStates UnitedStates TP
#> 5 mapsection5 Country UnitedStates UnitedStates TP
#> 6 mapsection1 Region Ontario Ontario TP
然后放置值列,并再次扩展为宽形状。您可以一步一步地完成并加入;分为两部分更容易解释。
joined %>%
select(-starts_with("value")) %>%
spread(key = level, value = truth)
#> MapSection Country Region Zone
#> 1 mapsection1 TP TP TP
#> 2 mapsection2 TP TP TP
#> 3 mapsection3 TP FN TN
#> 4 mapsection4 TP TP TP
#> 5 mapsection5 TP TP FP
由reprex package(v0.3.0)于2019-05-31创建
答案 1 :(得分:0)
按照布鲁斯的建议,我只提取了一个位置类型,并尝试评估了我描述的四个条件。我认为它在起作用...
Zone_df <- merge(true_map[,c("Zone", "MapSection")], obsrvd_map[,c("Zone", "MapSection")], by="MapSection") %>%
rename(., exp.Zone=Zone.x, obs.Zone=Zone.y) %>%
mutate_if(is.factor, as.character)
Zone_df %>%
mutate(EvalCase = case_when(
(exp.Zone) == (obs.Zone) ~ "TP",
is.na(exp.Zone) == is.na(obs.Zone) ~ "TN",
is.na(exp.Zone) & !is.na(obs.Zone) ~ "FP",
!is.na(exp.Zone) & is.na(obs.Zone) ~ "FN",
))