更改 data.frame 结构
change data.frame structure
我有两个 MySQL-table。其中一个包含犯罪案件的数据(即案件编号、地点),另一个包含 table [=21] 中每个案件的犯罪行为(即违反了哪条法律、文章、段落) =].因此,我与每个具有多项罪行的犯罪案件都有 1:n 关系。现在,我想加入两个 table,但不知道如何做到最好。
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 我应该将违规行为-table 变成这样的形式:
caseId / offence1law / offence1art / offence2law / offence2art / ...
---------------------
1 / law1 / 110 / law1 / 111 / ...
2 / law1 / 342 / law3 / 920 / ...
3 / law3 / 820 / NA / NA / ...
有人知道怎么做吗?我正在寻找的 table 中的变量数量取决于所犯的罪行数量。
非常感谢您的指点!
这是一个使用 dplyr
和 tidyr
来创建所需的攻击-table 信息的解决方案。 offences5
是最终输出。
想法是使用 gather
、unite
和 spread
来创建所需的宽格式 table。之后,使用left_join
合并数据。请注意,最后一个 select
和 setNames
正在选择和重命名与 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)
我有两个 MySQL-table。其中一个包含犯罪案件的数据(即案件编号、地点),另一个包含 table [=21] 中每个案件的犯罪行为(即违反了哪条法律、文章、段落) =].因此,我与每个具有多项罪行的犯罪案件都有 1:n 关系。现在,我想加入两个 table,但不知道如何做到最好。
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 我应该将违规行为-table 变成这样的形式:
caseId / offence1law / offence1art / offence2law / offence2art / ...
---------------------
1 / law1 / 110 / law1 / 111 / ...
2 / law1 / 342 / law3 / 920 / ...
3 / law3 / 820 / NA / NA / ...
有人知道怎么做吗?我正在寻找的 table 中的变量数量取决于所犯的罪行数量。
非常感谢您的指点!
这是一个使用 dplyr
和 tidyr
来创建所需的攻击-table 信息的解决方案。 offences5
是最终输出。
想法是使用 gather
、unite
和 spread
来创建所需的宽格式 table。之后,使用left_join
合并数据。请注意,最后一个 select
和 setNames
正在选择和重命名与 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)