Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/r/80.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
R 如果其他列匹配100%,则查找一列中最接近的值匹配_R_Data.table_Matching_Closest - Fatal编程技术网

R 如果其他列匹配100%,则查找一列中最接近的值匹配

R 如果其他列匹配100%,则查找一列中最接近的值匹配,r,data.table,matching,closest,R,Data.table,Matching,Closest,我有两个长度不等的数据帧。我想将值2从df2添加到df1,其中值1a和值1b之间的差异最小。并非df1中的所有行都将收到来自df2的匹配,因为df2较短。st、year和doy必须在df1和df2之间匹配,然后才能找到最接近的匹配值1a和1b,因为数据集包括在同一测站的几年内的多个采样 st <- c("ST1", "ST2", "ST2", "ST2", "ST3") year <-

我有两个长度不等的数据帧。我想将值2从df2添加到df1,其中值1a和值1b之间的差异最小。并非df1中的所有行都将收到来自df2的匹配,因为df2较短。st、year和doy必须在df1和df2之间匹配,然后才能找到最接近的匹配值1a和1b,因为数据集包括在同一测站的几年内的多个采样

st <- c("ST1", "ST2", "ST2", "ST2", "ST3")
year <- c(2011, 2011, 2012, 2012, 2013)
doy <- c(20,29,4,4,20)

value1a <- c(200, 250, 240, 250, 260)
value1b <- c(201, 258, 240, 251, 180)
value2 <- c(5,6,7,8.5,10)

df1 <- data.frame(st, year, doy, value1a)
df2 <- data.frame(st, year, doy, value1b, value2); df2 <- df2[1:4,]
我已经研究了最近的.match和相关函数,但在其他列中先前的匹配必须成功时,无法使其工作。有什么想法吗

*编辑:我根据下面的建议更改了数据帧,希望它能澄清问题。我向所有已经努力回答问题的人道歉


对于海洋学家在场的实际例子:我正在处理水柱数据。在一年中的同一天,在同一测站,根据水下深度的值1a,在第一次采样期间获得了某些数据。然后在一年的同一天重复此操作,只是稍微晚一点,因此年份和doy匹配,但自动记录的值1b略有不同。我想将仅在第二次采样时获得的值2与第一次采样时获得的数据进行匹配。

以下是一个基本的R解决方案:

df3 <- merge(df1, df2, by.x = c("st", "year", "doy"), by.y = c("st", "year", "doy2"), all = TRUE)
这将为您提供:

   st year doy value1a value1b value2
1 ST1 2011  20     200      NA     NA
2 ST1 2011  21      NA     201    5.0
3 ST2 2011  29     250     258    6.0
4 ST2 2012   4     240     240    7.0
5 ST2 2013  20     260     180    8.5

下面是一个基本的R解决方案:

df3 <- merge(df1, df2, by.x = c("st", "year", "doy"), by.y = c("st", "year", "doy2"), all = TRUE)
这将为您提供:

   st year doy value1a value1b value2
1 ST1 2011  20     200      NA     NA
2 ST1 2011  21      NA     201    5.0
3 ST2 2011  29     250     258    6.0
4 ST2 2012   4     240     240    7.0
5 ST2 2013  20     260     180    8.5

这里是dplyr包的一个很长的替代方案


这里是dplyr包的一个很长的替代方案


试图消除value1a和value1b之间的差异是一个极小的语句,这是一个两步操作:合并/加入,然后根据差异减少

因为当前的示例数据没有测试这个需求,所以我将使用稍微不同的值复制其中一行,以显示正在选择最小值

df2% mutatern=行数%>% 左联合,df2,by=cst,年份,doy=doy2%>% 排列AbsValue1a-value1b%>% 组\u byrn%>% 切片1%>% 解组 一个tibble:4x7 第一年doy价值1a注册护士价值1b价值2 1 ST1 2011 20 200 1不适用 2 ST2 2011 29 250 2 258 6 3 ST2 2012 4 240 3 240 7 4 ST2 2013 2026041808.5 数据表 一些注意事项:

我使用magrittr的pipe%>%纯粹是为了演示,因为我认为它在视觉上表现得非常出色;这不是必需的 在data.table合并内容的方式中,doy字段保留了正确表df2的名称,因此我使用data.table::setnames对其进行了重命名 data.table中的一个小功能/错误阻止了在最后一个[-操作是带有:=”的赋值时第一次打印结果;这是,并且只是美观,如果有另一个操作,这不是一个因素;因此,我添加了一个看似空的%>%.[]将其打印到控制台 图书馆数据表 图书馆杂志 setDTdf1 setDTdf2 df1[,rn:=.I]]>% df2[,on=.st,年份,doy2=doy]>% [orderabsvalue1a-value1b,]%>% [,.SD[1,],by=.rn]]>% [,rn:=NULL]]>% 集合名称,旧=doy2,新=doy%>% .[] 第一年doy值1b值2值1a 1:ST2 2012 4 240 7.0 240 2:ST2 2011 29 258 6.0 250 3:ST2 2013 20 180 8.5 260 4:ST1 2011 20 NA 200 有很多方法可以告诉data.table在找到多个匹配项时要做什么。我没有测试顺序是否可以确定,但如果有一种方法可以确定这一点,那么这可能可以简化一点

类SQL 使用df1和df2的原始not-data.table版本

出于类似的原因,这将创建两个行号计数器,类似于data.table解决方案中的rn

sqldf::sqldf 以t1为例 选择df1.*,行号为rn1 来自df1 , t12 as 选择t1.*,t2.value2, t1.rn1作为rn2分区上的行数 从t1开始 左连接t1上的df2 t2。st=t2.st和t1。year=t2.year和t1.doy=t2.doy2 absvalue1a-value1b下的订单 从t12中选择st、year、doy、value1a、value2,其中rn2=1 第一年doy值1a值2 1 ST1 2011 20 200 NA 2 ST2 2012 4 240 7.0 3 ST2 2011 29 250 6.0 4 ST2 2013 20 260 8.5
试图消除value1a和value1b之间的差异是一个极小的语句,这是一个两步操作:合并/加入,然后根据差异减少

因为当前的示例数据没有测试这个需求,所以我将使用稍微不同的值复制其中一行,以显示正在选择最小值

df2% mutatern=行数%>% 左联合,df2,by=cst,年份,doy=doy2%>% 排列AbsValue1a-value1b%>% 组\u byrn%>% 切片1%>% 解组 一个tibble:4x7 第一年doy价值1a注册护士价值1b价值2 1 ST1 2011 20 200 1不适用 2011年2月2日 29 250 2 258 6 3 ST2 2012 4 240 3 240 7 4 ST2 2013 2026041808.5 数据表 一些注意事项:

我使用magrittr的pipe%>%纯粹是为了演示,因为我认为它在视觉上表现得非常出色;这不是必需的 在data.table合并内容的方式中,doy字段保留了正确表df2的名称,因此我使用data.table::setnames对其进行了重命名 data.table中的一个小功能/错误阻止了在最后一个[-操作是带有:=”的赋值时第一次打印结果;这是,并且只是美观,如果有另一个操作,这不是一个因素;因此,我添加了一个看似空的%>%.[]将其打印到控制台 图书馆数据表 图书馆杂志 setDTdf1 setDTdf2 df1[,rn:=.I]]>% df2[,on=.st,年份,doy2=doy]>% [orderabsvalue1a-value1b,]%>% [,.SD[1,],by=.rn]]>% [,rn:=NULL]]>% 集合名称,旧=doy2,新=doy%>% .[] 第一年doy值1b值2值1a 1:ST2 2012 4 240 7.0 240 2:ST2 2011 29 258 6.0 250 3:ST2 2013 20 180 8.5 260 4:ST1 2011 20 NA 200 有很多方法可以告诉data.table在找到多个匹配项时要做什么。我没有测试顺序是否可以确定,但如果有一种方法可以确定这一点,那么这可能可以简化一点

类SQL 使用df1和df2的原始not-data.table版本

出于类似的原因,这将创建两个行号计数器,类似于data.table解决方案中的rn

sqldf::sqldf 以t1为例 选择df1.*,行号为rn1 来自df1 , t12 as 选择t1.*,t2.value2, t1.rn1作为rn2分区上的行数 从t1开始 左连接t1上的df2 t2。st=t2.st和t1。year=t2.year和t1.doy=t2.doy2 absvalue1a-value1b下的订单 从t12中选择st、year、doy、value1a、value2,其中rn2=1 第一年doy值1a值2 1 ST1 2011 20 200 NA 2 ST2 2012 4 240 7.0 3 ST2 2011 29 250 6.0 4 ST2 2013 20 260 8.5
因此,我使用dplyr和left_join参数,而left_join参数本身并不能得到正确的答案。然后,我使用group_by对行进行分组。分组后,通过比较value1a和value1b的不同值的绝对值,可以过滤出彼此不接近的值。您必须包含一个addi筛选器中的逻辑语句,以便在计算其他NA语句时不会自动删除带有NAs的行。因此,它看起来如下所示:

     st year    doy value1a value1b value2
1   ST1 2011    20  200      201    5.0
2   ST2 2011    29  250      258    6.0
3   ST2 2012    4   240      240    7.0
4   ST2 2012    4   250      251    8.5
5   ST3 2013    20  260      NA     NA
library(dplyr)
df3 <- left_join(df1, df2, by = c("st", "year", "doy"))
df3 %>% group_by(st, year, doy, value1a) %>%
  filter(is.na(value1b) | abs(value1a - value1b) == 
           min(abs(value1a - value1b)))
我得到的结果如下:

st     year   doy value1a value1b value2
  <fct> <dbl> <dbl>   <dbl>   <dbl>  <dbl>
1 ST1    2011    20     200     201    5  
2 ST2    2011    29     250     258    6  
3 ST2    2012     4     240     240    7  
4 ST2    2012     4     250     251    8.5
5 ST3    2013    20     260      NA   NA 

因此,我使用dplyr和left_join参数,而left_join参数本身并不能得到正确的答案。然后,我使用group_by对行进行分组。分组后,通过比较value1a和value1b的不同值的绝对值,可以过滤出彼此不接近的值。您必须包含一个addi筛选器中的逻辑语句,以便在计算其他NA语句时不会自动删除带有NAs的行。因此,它看起来如下所示:

     st year    doy value1a value1b value2
1   ST1 2011    20  200      201    5.0
2   ST2 2011    29  250      258    6.0
3   ST2 2012    4   240      240    7.0
4   ST2 2012    4   250      251    8.5
5   ST3 2013    20  260      NA     NA
library(dplyr)
df3 <- left_join(df1, df2, by = c("st", "year", "doy"))
df3 %>% group_by(st, year, doy, value1a) %>%
  filter(is.na(value1b) | abs(value1a - value1b) == 
           min(abs(value1a - value1b)))
我得到的结果如下:

st     year   doy value1a value1b value2
  <fct> <dbl> <dbl>   <dbl>   <dbl>  <dbl>
1 ST1    2011    20     200     201    5  
2 ST2    2011    29     250     258    6  
3 ST2    2012     4     240     240    7  
4 ST2    2012     4     250     251    8.5
5 ST3    2013    20     260      NA   NA 

以下是在data.table中使用滚动联接的选项:

输出:

   value1a  st year doy value1b value2
1:     200 ST1 2011  20     200    5.0
2:     250 ST2 2011  29     250    6.0
3:     240 ST2 2012   4     240    7.0
4:     250 ST2 2012   4     250    8.5
5:     260 ST3 2013  20     260     NA

以下是在data.table中使用滚动联接的选项:

输出:

   value1a  st year doy value1b value2
1:     200 ST1 2011  20     200    5.0
2:     250 ST2 2011  29     250    6.0
3:     240 ST2 2012   4     240    7.0
4:     250 ST2 2012   4     250    8.5
5:     260 ST3 2013  20     260     NA

因为你说差异…是最小的,我猜合并/连接中应该有逻辑来比较这两个变量。因此,我建议你提供一个df2,其中包括一组或多组密钥上的多个匹配,需要后续最小化。你是对的,示例数据没有显示真正的问题。我将尝试提供更合适的数据。因为您说过差异…最小,所以我猜合并/连接中应该有逻辑来比较这两个变量。因此,我建议您提供一个df2,其中包括一组或多组密钥上的多个匹配项,要求后续最小化。您是对的,示例如下数据没有显示真正的问题。我将尝试提供更合适的数据。1如果您打算指示某些内容,请不要使用NA的文字字符串……首先,您将所有数据从数字更改为字符串;其次,如果您的意思是找不到匹配项,请使用NA,而不是NA。2此方法仅在所有行都已完全对齐时才有效,这是一个坏主意。3请求的操作是合并/联接,答案并非如此。1如果要指示某些内容,请不要使用NA的文字字符串…首先,您将所有数据从数字更改为字符串;其次,如果您的意思是未找到匹配项,请使用NA,而不是NA。2此方法仅在所有行都已完全对齐时才有效,这是一个坏主意。3请求的操作是一个合并/联接,答案不是这样。非常感谢!一旦我了解了它的作用,并且在我的原始数据中,value1a和value1b实际上具有相同的列名,在联接后重命名为value.x和value.y,它就像一个符咒一样工作!非常感谢!一旦我了解了 在我的原始数据中,value1a和value1b实际上具有相同的列名,在连接后重命名为value.x和value.y,它工作得非常出色!