【问题标题】:Merge two dataframes based on common two columns & if values in third column are nearest to each other基于共同的两列合并两个数据框,如果第三列中的值彼此最接近
【发布时间】:2016-10-14 23:52:20
【问题描述】:

我陷入了合并两个数据集的困境,其简单的复杂性远远超出了我对 R 的流利程度。我尝试向herehere 学习,但无法解决我的问题。我正在尝试合并以下两个数据框:

df1

No    County       Route      Number
1     Anderson       SR009       6150
2     Anderson       SR061       5880
3     Bedford        SR016       9500
4     Bedford        SR130       320
5       .
6       .
7       .
8       .

df2

No.  County        Route     Number1    abc      def
1    Clay          02264     4500        50       789
2     Dickson       01544     5870       45       33
3     Anderson      01421     981        70       65
4     Anderson      SR009     10000      56       56
5     Anderson      SR009     6145       32       53
6     Bedford       SR016     7500       23       32
7     Anderson      SR061     4400       12       24
8     Anderson      SR061     5875       87       26
9     Anderson      SR061     15000      45       45
10     Bedford       SR016     22000     71       75
11     Bedford       SR016     9450      145      615
12     Bedford       SR130     900       7854     76
13     Bedford       SR130     310       124      25
14     Anderson      SR061     5865      312      123
       .
       .
       .

首先,应比较 df1 和 df2 中的“县”和“路线”列,如果它们完全匹配,则应选择 df2$Number1 的特定行,其值与 df1$Number 最接近,因此所有唯一的 df2 列都应添加到 df1

这是我想要实现的伪代码:

if(df1$County == Anderson & df2$County == Anderson) && if(df1$Route == SR009 & df2$Route == SR009) 
then select specific row from df2$Number1 whose value is nearest to the df1$Number value, 
and add all subsequent columns of df2 to corresponding row in df1

一个例子:

根据“County”和“Route”列,df1 中的第 1 行与 df2 中的第 4 行和第 5 行匹配。现在,在与 df1 中的第一行匹配的两个 df2 行中,我想在 df2 中选择其“Number1”值最接近 df1 中的“Number”值的特定行,即 6150。说这个,我想选择行df2 中的 5,因为“Number1”值是最接近 6150 的 6145,并将所有后续列从 df2 添加到 df1...

最终输出如下所示:

No      County           Route       Number     Number1     abc    def  .  .    
1       Anderson         SR009       6150       6145        32     53   .  .
2       Anderson         SR061       5880       5875        87     26   .  .
3       Bedford          SR016       9500       9450        145    615  .  .
4       Bedford          SR139       320        310         124    25   .  .
.          .
.          .

我非常感谢您对此提供的任何帮助。抱歉,帖子太长了。

【问题讨论】:

    标签: r


    【解决方案1】:

    你的问题有点混乱。尽管如此,根据您想要的输出,我认为以下dplyr 方法对您有用。

    library(dplyr)
    
    d1%>%
      full_join(d2, by = c("County", "Route")) %>%
      group_by(County, Route) %>%
      mutate(myDiff = abs(Number - Number1)) %>%
      slice(which.min(myDiff))
    

    【讨论】:

    • 感谢您的回复。
    • 警告信息:1:在 full_join_impl(x, y, by$x, by$y, suffix$x, suffix$y) 中:加入不同级别的因子,强制到字符向量 2:在full_join_impl(x, y, by$x, by$y, suffix$x, suffix$y) : 加入不同层级的因子,强制转换成字符向量
    • @B.WNiazi 我也是。但是,这不是错误,而是在这种情况下可以忽略的警告。用简单的英语,警告是说数据中的一些变量是因素。但是,这些因素的水平在数据帧中并不一致。因此R 将在合并/加入之前将因子转换为字符。
    • 感谢您的指导。它返回一个具有 0 个观察值的空数据框
    【解决方案2】:

    使用library(data.table)

    setkey(dt1, County, Route)
    setkey(dt2, County, Route)
    dt3 = dt1[dt2]
    dt3[, Number.close := Number1[which.min(abs(Number1-Number))], by = .(County, Route)]
    dt3 = dt3[Number.close == Number1, ][, Number.close:=NULL][]
    
    #    No   County Route Number No. Number1 abc def
    # 1:  1 Anderson SR009   6150   5    6145  32  53
    # 2:  2 Anderson SR061   5880   8    5875  87  26
    # 3:  3  Bedford SR016   9500  11    9450 145 615
    # 4:  4  Bedford SR130    320  13     310 124  25
    

    数据:

    dt1 = structure(list(No = 1:4, County = c("Anderson", "Anderson", "Bedford", 
    "Bedford"), Route = c("SR009", "SR061", "SR016", "SR130"), Number = c(6150L, 
    5880L, 9500L, 320L)), .Names = c("No", "County", "Route", "Number"
    ), row.names = c(NA, -4L), class = c("data.table", "data.frame"
    ), .internal.selfref = <pointer: 0x000000000b290788>, sorted = c("County", 
    "Route"))
    
    dt2 = structure(list(No. = c(3L, 4L, 5L, 7L, 8L, 9L, 14L, 6L, 10L, 
    11L, 12L, 13L, 1L, 2L), County = c("Anderson", "Anderson", "Anderson", 
    "Anderson", "Anderson", "Anderson", "Anderson", "Bedford", "Bedford", 
    "Bedford", "Bedford", "Bedford", "Clay", "Dickson"), Route = c("01421", 
    "SR009", "SR009", "SR061", "SR061", "SR061", "SR061", "SR016", 
    "SR016", "SR016", "SR130", "SR130", "02264", "01544"), Number1 = c(981L, 
    10000L, 6145L, 4400L, 5875L, 15000L, 5865L, 7500L, 22000L, 9450L, 
    900L, 310L, 4500L, 5870L), abc = c(70L, 56L, 32L, 12L, 87L, 45L, 
    312L, 23L, 71L, 145L, 7854L, 124L, 50L, 45L), def = c(65L, 56L, 
    53L, 24L, 26L, 45L, 123L, 32L, 75L, 615L, 76L, 25L, 789L, 33L
    )), .Names = c("No.", "County", "Route", "Number1", "abc", "def"
    ), row.names = c(NA, -14L), class = c("data.table", "data.frame"
    ), .internal.selfref = <pointer: 0x000000000b290788>, sorted = c("County", 
    "Route"))
    

    【讨论】:

    • 可能遗漏了重要的一点。运行以下代码后,我得到一个空的 dt3 帧... setkey(mydataa, County, Route) setkey(mydata11, County, Route) dt3 = mydataa[mydata11] dt3[, AADT.close := AADT[which.min( abs(AADT2015-AADT))], by = .(County, Route)] dt3 = dt3[AADT.close == AADT2015, ][, AADT.close:=NULL]
    • 你确定吗?尝试print(dt3) - 请参阅stackoverflow.com/questions/32988099/… - 有时您必须打印两次才能在 data.table 中使用 := 后查看输出。这是另一个错误修复的副作用
    • 我只是在最后一行的末尾添加了一个额外的[],以避免这个问题。
    • 感谢您的努力。添加 [] 后,现在它返回一个 12000 行(df2 大小)的数据框,而它应该返回一个 336 行(df1 大小)的数据表,并且 dt3 中的所有值都是“NA”。
    • 好吧,在您的最小示例上看起来不错,我想这一定与您运行它的数据与您的最小示例之间的差异有关。在不确切了解您在做什么的情况下进行诊断很棘手
    猜你喜欢
    • 2019-05-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2018-01-30
    • 2021-12-17
    • 2023-01-22
    • 2021-01-11
    • 1970-01-01
    相关资源
    最近更新 更多