【问题标题】:change data.frame structure改变data.frame结构
【发布时间】:2017-08-26 18:26:10
【问题描述】:

我有两个 MySQL 表。其中一个包含犯罪案件的数据(即案件编号、地点),另一个包含“案件”表中每个案件的犯罪行为(即违反了哪条法律、文章、段落)。因此,我与每个具有多项罪行的犯罪案件都有 1:n 的关系。现在,我想加入这两个表,但不知道如何做到最好。

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 我应该把 offences-table 变成这样的形式:

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

有人知道怎么做吗?我要查找的表中变量的数量取决于所犯的罪行数量。

非常感谢您的提示!

【问题讨论】:

  • 您的结果根本不使用您的第一个表;它只是你的第二个更广泛的形式。虽然您可以使用 tidyr 创建它,但我最好的建议是不要这样做,因为它是一个不整洁且不太有用的数据结构,变量隐藏在列名中。
  • 那么您想通过caseId 加入吗? dplyr有加入功能,比如left_join
  • @Dambo 加入不是这里的问题。问题是,“右”表与“左”表的结构不同。
  • @alistaire 感谢您的回答!我同意,我想获得的桌子不会“整洁”。但是我不知道在分析案例表时如何整合表“罪行”。例如,如果我想回答有多少百分比的案件存在违法行为1(例如)。

标签: r dataframe dplyr reshape tidyr


【解决方案1】:

这是使用dplyrtidyr 来创建所需的犯罪表信息的解决方案。 offences5 是最终输出。

这个想法是使用gatherunitespread 来创建所需的宽格式表。之后,使用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)

【讨论】:

    猜你喜欢
    • 2019-05-06
    • 1970-01-01
    • 2021-07-30
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2020-07-09
    • 1970-01-01
    • 2011-12-19
    相关资源
    最近更新 更多