2017-08-26 1 views
0

Ich habe zwei MySQL-Tabellen. Einer von ihnen enthält Daten von Verbrechensfällen (d. H. Fallnummern, Orte), der andere enthält die Verbrechensdelikte, die begangen wurden (d.h. welches Gesetz wurde gebrochen, Artikel, Paragraph) für jeden Fall in der Tabelle "Fälle". Daher habe ich eine 1: n-Beziehung zu jedem Straffall mit mehreren Straftaten. Nun möchte ich mich beiden Tabellen anschließen, habe aber keine Ahnung, wie ich das am besten mache.ändern data.frame Struktur

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 /... 

Um beide data.frames beizutreten, ich sollte die Straftaten-Tabelle in eine Form, wie das erhalten:

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

Weiß jemand, wie man dies zu tun? Die Anzahl der Variablen in der von mir gesuchten Tabelle hängt von der Anzahl der begangenen Straftaten ab.

Vielen Dank für Ihre Hinweise!

+1

Ihr Ergebnis verwendet nicht Ihre erste Tabelle überhaupt; es ist nur eine breitere Form deines zweiten. Obwohl Sie es mit tidyr erstellen könnten, ist mein bester Rat, dies nicht zu tun, da es eine unordentliche und weniger nützliche Datenstruktur mit in den Spaltennamen versteckten Variablen ist. – alistaire

+0

Also willst du mit 'caseId' teilnehmen? 'dplyr' hat Join-Funktionen, check' left_join' zum Beispiel – Dambo

+0

@ Dambo Joining ist nicht das Problem hier. Das Problem ist, dass die "richtige" Tabelle eine andere Struktur hat als die "linke" Tabelle. –

Antwort

1

Hier ist eine Lösung mit dplyr und tidyr, um die gewünschte Angriffstabelle Informationen zu erstellen. offences5 ist die endgültige Ausgabe.

Die Idee besteht darin, gather, unite und spread zu verwenden, um gewünschte Wide-Format-Tabelle zu erstellen. Danach verwenden Sie left_join, um die Daten zu kombinieren. Beachten Sie, dass die letzten select und setNames die Spalten genau so auswählen und umbenennen, wie die vom OP gewünschte Ausgabe. Wenn die Reihenfolge der Spalten nicht wichtig ist, sind diese Aufrufe optional.

Die Lösung hat nichts mit dem Datenrahmen cases zu tun. Wenn das OP jedoch möchte, wäre es leicht, eine left_join durchzuführen, wenn offences5 bereit ist.

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 

Daten:

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) 
Verwandte Themen