2017-08-26 238 views
0

我有两个MySQL表。其中一个包含犯罪案件的数据(即案件号码,地点),另一个案件包含针对案件“案件”表格中每个案件提交的犯罪行为(即违反哪些法律,条款,段落)。因此,我与每一起犯有多重罪行的案件都有1:n的关系。现在,我想加入这两个表格,但不知道如何做到最好。更改data.frame结构

table "cases" 
ID/casenumber/... 
--------------------- 
1/2015-33323 
2/2016-33213 
3/2017-88873 


table "offences" 
ID/caseId/law/article/... 
--------------------- 
1/1  /law1/110 /... 
2/1  /law1/111 /... 
3/1  /law2/239 /... 
4/2  /law1/342 /... 
5/2  /law3/920 /... 
6/3  /law1/820 /... 

为了加入两个data.frames我应该得到的罪行表成这样一种形式:

caseId/offence1law/offence1art/offence2law/offence2art/... 
--------------------- 
1 /law1  /110  /law1  /111/... 
2 /law1  /342  /law3  /920/... 
3 /law3  /820  /NA  /NA/... 

有谁知道如何做到这一点?我所寻找的表格中的变量数量取决于所犯罪行的数量。

非常感谢您的提示!

+1

您的结果不使用你的第一个表中的所有;这只是你的第二个更广泛的形式。虽然你可以使用tidyr创建它,但我最好的建议是不要这样做,因为它是一个杂乱无章且数据结构不太好的数据结构,其变量隐藏在列名称中。 – alistaire

+0

所以你想加入'caseId'? 'dplyr'已加入函数,请检查'left_join'例如 – Dambo

+0

@ Dambo加入并不是问题。问题是,“右”表具有与“左”表不同的结构。 –

回答

1

以下是使用dplyrtidyr创建所需的进攻表信息的解决方案。 offences5是最终输出。

想法是使用gather,unitespread来创建所需的宽格式表格。之后,使用left_join来合并数据。请注意,最后的selectsetNames正在选择并重命名与OP所需输出完全相同的列。但是,如果列顺序不重要,则这些调用是可选的。

该解决方案与cases数据帧无关。但是,如果OP需要,如果offences5准备就绪,则很容易进行left_join

library(dplyr) 
library(tidyr) 

offences2 <- offences %>% 
    group_by(caseId) %>% 
    mutate(ID = 1:n(), Law = "law", Art = "art") %>% 
    unite(Law2, ID, Law, remove = FALSE, sep = "") %>% 
    unite(Art2, ID, Art, remove = TRUE, sep = "") 

offences3 <- offences2 %>% 
    select(caseId, law, Law2) %>% 
    spread(Law2, law) 

offences4 <- offences2 %>% 
    select(caseId, article, Art2) %>% 
    spread(Art2, article) 

offences5 <- offences3 %>% 
    left_join(offences4, by = "caseId") %>% 
    select(c("caseId", sapply(1:length(unique(offences$law)), 
          function(i) paste0(i, c("law", "art"))))) %>% 
    setNames(c("caseId", paste0("offence", colnames(.[, -1])))) 

offences5 
# A tibble: 3 x 7 
# Groups: caseId [3] 
    caseId offence1law offence1art offence2law offence2art offence3law offence3art 
    <int>  <chr>  <int>  <chr>  <int>  <chr>  <int> 
1  1  law1   110  law1   111  law2   239 
2  2  law1   342  law3   920  <NA>   NA 
3  3  law1   820  <NA>   NA  <NA>   NA 

数据:

offences <- read.table(text = "ID caseId law article 
         1 1 law1 110 
         2 1 law1 111 
         3 1 law2 239 
         4 2 law1 342 
         5 2 law3 920 
         6 3 law1 820", 
         header = TRUE, stringsAsFactors = FALSE)