【问题标题】:Concatenate in R (equivalent of COALESCE when using sqldf)在 R 中连接(使用 sqldf 时相当于 COALESCE)
【发布时间】:2016-07-06 00:52:45
【问题描述】:

我正在尝试创建一个审核报告,该报告采用呼叫日志数据 [表 1] 并将其与时间表数据 [表 2] 进行比较。如果有与时间表数据 [表 2] 匹配的通话记录数据 [表 1] 的记录,我需要一个简单的查询来返回“OK”。

表 1

Date            Project Code    Amount  Employee
11/2/15         30018           250     Tom Thompson
11/2/15         30018           500     John Johnson
11/2/15         20018           500     Jane Doe

表 2

Project Code    Project Name    Employee       Hours    Dates
30012           A               Jane Doe       4        11/2/15
3200            B               Jane Doe       2        11/2/15
4               C               Jane Doe       1        11/2/15
20018           D               Jane Doe       1        11/2/15
4               C               John Johnson   6        11/2/15

我在 R 中使用 sqldf 包,运行以下命令:

test2 = sqldf("
    SELECT a.*,
    CASE
        WHEN
            a.Name = b.employee and a.Date=b.Dates AND
            a.Project like b.ProjectCode
        THEN 'Okay'
        ELSE 'Flag'
        END 'Audit'

    FROM Table_1 as a, Table_2 as b
    WHERE a.Name = b.employee
    GROUP BY a.Name
")

这不会返回我需要的东西。维护 SQL 逻辑我想连接表 2(或分组依据)以产生:

Project Code            Employee    Dates
30012, 3200, 4, 20018   Jane Doe    11/2/15

我的想法是,我可以在上面的 case 语句中使用“like”语句,它会起作用。

【问题讨论】:

  • 我没有得到第一个表的角色。根本不使用Table_1 就不能获得输出吗?

标签: sql r sqldf


【解决方案1】:

您可以使用aggregatepaste 在base R 中实现所需的输出:

aggregate(Project_Code ~ Employee + Dates, data=df, paste, sep=",")
      Employee   Dates          Project_Code
1     Jane_Doe 11/2/15 30012, 3200, 4, 20018
2 John_Johnson 11/2/15                     4

还有几个其他函数会返回这个结果。正如@nicola 提到的,您也可以使用toString 来实现这一点。另一个选项是c

aggregate(Project_Code ~ Employee + Dates, data=df, c)

看起来是上面的结果。


但是请注意,此数据的结构比最初出现的要复杂。这是在输出上使用strc 的结果:

'data.frame':2 obs。 3 个变量:
$ Employee : Factor w/ 2 个级别 "Jane_Doe","John_Johnson": 1 2
$ 日期:因子 w/ 1 级“11/2/15”:1 1
$ Project_Code:2个列表
..$ 1.1: int 30012 3200 4 20018
..$ 1.2: int 4

所以程序代码变量实际上是一个列表。如果这是一个问题,您可以使用 pastecollapse =", " 参数让它返回一个字符串变量,看起来或多或少相同:

aggregate(Project_Code ~ Employee + Dates, data=df, paste, collapse=", ")
      Employee   Dates          Project_Code
1     Jane_Doe 11/2/15 30012, 3200, 4, 20018
2 John_Johnson 11/2/15                     4

但结构更简单。

数据

df <- read.table(header=T, text="Project_Code  Project_Name    Employee    Hours    Dates
30012           A               Jane_Doe       4        11/2/15
3200            B               Jane_Doe       2        11/2/15
4               C               Jane_Doe       1        11/2/15
20018           D               Jane_Doe       1        11/2/15
4               C               John_Johnson   6        11/2/15")

【讨论】:

  • 你可以直接用toString代替paste
  • toString 在某些方面效率更高吗?
  • 对于程序员来说是这样,因为您节省了一些击键 :) 开玩笑,猜它效率较低,但可以选择。
【解决方案2】:

使用R,我们可以在两个数据集之间做一个left_join,然后按'Employee'、'Dates'、paste'ProjectCode'分组(toStringpaste(., collapse=', ')的包装器)

library(dplyr)
left_join(Table_2, Table_1, by = c("ProjectCode", "Dates" = "Date", "Employee")) %>% 
    group_by(Employee, Dates) %>%
    summarise(ProjectCode = toString(ProjectCode))
 #     Employee   Dates           ProjectCode
 #        <chr>   <chr>                 <chr>
 #1     Jane Doe 11/2/15 30012, 3200, 4, 20018
 #2 John Johnson 11/2/15                     4

正如@nicola 提到的,我们可以只使用'Table_2'来获得输出

 Table_2 %>%
      group_by(Employee, Dates) %>%
      summarise(ProjectCode = toString(ProjectCode)) 
 #    Employee   Dates           ProjectCode
 #        <chr>   <chr>                 <chr>
 #1     Jane Doe 11/2/15 30012, 3200, 4, 20018
 #2 John Johnson 11/2/15                     4

数据

 Table_1 <- structure(list(Date = c("11/2/15", "11/2/15", "11/2/15"), 
 ProjectCode = c(30018L, 
 30018L, 20018L), Amount = c(250L, 500L, 500L), Employee = c("Tom Thompson", 
 "John Johnson", "Jane Doe")), .Names = c("Date", "ProjectCode", 
 "Amount", "Employee"), class = "data.frame", row.names = c(NA, -3L))

 Table_2 <- structure(list(ProjectCode = c(30012L, 3200L, 4L, 20018L, 4L), 
ProjectName = c("A", "B", "C", "D", "C"), Employee = c("Jane Doe", 
"Jane Doe", "Jane Doe", "Jane Doe", "John Johnson"), Hours = c(4L, 
2L, 1L, 1L, 6L), Dates = c("11/2/15", "11/2/15", "11/2/15", 
"11/2/15", "11/2/15")), .Names = c("ProjectCode", "ProjectName", 
"Employee", "Hours", "Dates"), class = "data.frame",
 row.names = c(NA, -5L))

【讨论】:

  • 我猜你可以保存join 部分...我不明白第一个表的目的是什么。
  • @nicola 我对第一张桌子有点困惑。
【解决方案3】:

问题中的描述、输入、输出和代码都不一致(例如,代码指的是名称输入和审计输出列,但都没有出现在所示的输入和输出中),因此我们假设了注释中的输入最后,问题输出中显示的列并修改了代码以解决不一致并使用group_concat

代码可能还有其他问题,但需要进一步澄清解决这些问题的意图,特别是关于 Audit 列是否应该被计算,即使没有出现在示例输出中,如果是这样,确切地说它代表什么以及主题中对合并的引用指的是什么。

library(sqldf)

sqldf("SELECT group_concat(b.ProjectCode) as 'Project Code', a.Name, b.Dates
              FROM Table_1 as a
              JOIN Table_2 as b ON a.Name = b.employee
              GROUP BY a.Name")

给予:

                 Project Code         Name   Dates
1          4,3200,20018,30012     Jane_Doe 11/2/15
2                           4 John_Johnson 11/2/15

注意:这些输入是假设的:

Lines1 <- "Date            Project    Amount  Name
11/2/15         30018           250     Tom_Thompson
11/2/15         30018           500     John_Johnson
11/2/15         20018           500     Jane_Doe"

Lines2 <- "ProjectCode    Name    Employee       Hours    Dates
30012           A               Jane_Doe       4        11/2/15
3200            B               Jane_Doe       2        11/2/15
4               C               Jane_Doe       1        11/2/15
20018           D               Jane_Doe       1        11/2/15
4               C               John_Johnson   6        11/2/15"

Table_1 <- read.table(text = Lines1, header = TRUE)
Table_2 <- read.table(text = Lines2, header = TRUE)

【讨论】:

    【解决方案4】:

    您可以使用EXISTS 子查询轻松做到这一点:

    SELECT a.*,
           (CASE WHEN EXISTS (SELECT 1 FROM table_2 b WHERE a.Name = b.employee)
                 THEN 'Okay'
                 ELSE 'Flag'
            END) as Audit
    FROM Table_1 a;
    

    【讨论】:

    • 谢谢,戈登!如果在同一日期有多个条目,那会起作用吗? IE。一个日期有多个项目,如果其中一个成功了,那么“好的”?
    • 如果b中有多行就可以了。
    猜你喜欢
    • 2016-11-19
    • 2015-06-09
    • 2020-08-15
    • 1970-01-01
    • 1970-01-01
    • 2015-03-15
    • 1970-01-01
    • 2022-01-10
    • 2018-07-25
    相关资源
    最近更新 更多