首页 > 解决方案 > R - 仅对最接近的整数进行模糊连接

问题描述

假设我有这个数据集开始,在这个愚蠢的布局中:

在此处输入图像描述

originalDF <- data.frame(
  Index = 1:14,
  Field = c("Name",     "Weight",   "Age",  "Name",     "Weight",   "Age",  "Height",   "Name",     "Weight",   "Age",  "Height",   "Name",     "Age",  "Height"),
  Value = c("Sara",     "115",  "17",   "Bob",  "158",  "22",   "72",   "Irv",  "210",  "42",   "68",   "Fred",     "155",  "65")
  )

我希望它看起来像这样:

在此处输入图像描述

基本上,我想将 Weight、Age 和 Height 行与其上方的 Name 行匹配。拆分数据很容易使用dplyr

namesDF <- originalDF %>%
  filter(Field == "Name")

detailsDF <- originalDF %>%
  filter(!Field == "Name")

从这里开始,使用索引(行号)似乎是最好的方法,即将每一行与具有最接近索引detailsDF的条目匹配而不重复。namesDF我使用了这个fuzzyjoin包并加入了他们

fuzzy_left_join(detailsDF, namesDF, by = "Index", match_fun = list(`>`))

这种工作方式,但它也将每一行与每一行连接detailsDF在一起,namesDF并具有较小的索引号:

在此处输入图像描述

我想出了一个解决方案,使用到下一个索引的距离并以这种方式过滤掉多余的行,但我想避免这样做;实际的源文件将超过 200k 行,并且带有额外行的临时结果数据框太大而无法放入内存。有什么我可以在这里做的吗?谢谢!

标签: rdplyrfuzzyjoin

解决方案


我建议以不同的方式接近它,通过跟踪每个点的最新“名称”值。fill()来自 tidyr 包对此很有用。

library(dplyr)
library(tidyr)

originalDF %>%
  mutate(Name = ifelse(Field == "Name", as.character(Value), NA)) %>%
  fill(Name) %>%
  filter(Field != "Name")

输出:

   Index  Field Value Name
1      2 Weight   115 Sara
2      3    Age    17 Sara
3      5 Weight   158  Bob
4      6    Age    22  Bob
5      7 Height    72  Bob
6      9 Weight   210  Irv
7     10    Age    42  Irv
8     11 Height    68  Irv
9     13    Age   155 Fred
10    14 Height    65 Fred

但是,如果您确实想使用模糊连接方法,您可以在结果中实现这一点,您可以group_by()slice()其中获取每个值的最后一行Index.x

fuzzy_left_join(detailsDF, namesDF, by = "Index", match_fun = list(`>`)) %>%
  group_by(Index.x) %>%
  slice(n()) %>%
  ungroup()

输出:

# A tibble: 10 x 6
   Index.x Field.x Value.x Index.y Field.y Value.y
     <int> <fct>   <fct>     <int> <fct>   <fct>  
 1       2 Weight  115           1 Name    Sara   
 2       3 Age     17            1 Name    Sara   
 3       5 Weight  158           4 Name    Bob    
 4       6 Age     22            4 Name    Bob    
 5       7 Height  72            4 Name    Bob    
 6       9 Weight  210           8 Name    Irv    
 7      10 Age     42            8 Name    Irv    
 8      11 Height  68            8 Name    Irv    
 9      13 Age     155          12 Name    Fred   
10      14 Height  65           12 Name    Fred   

推荐阅读