Jas*_*lns 1 r dplyr tidyr data-munging
给出以下数据框:
df <- data.frame(start = c("005", "010", "014"),
end = c("005", "013", "017"),
zone = c(3, 5, 7))
# df
# start end zone
# 1 005 005 3
# 2 010 013 5
# 3 014 017 7
Run Code Online (Sandbox Code Playgroud)
我想生成以下结果:
# key zone
# 1 005 3
# 2 010 5
# 3 011 5
# 4 012 5
# 5 013 5
# 6 014 7
# 7 015 7
# 8 016 7
# 9 017 7
Run Code Online (Sandbox Code Playgroud)
我想我可以利用一些东西tidyr- 也许complete()或者expand(),但是有三个字符的字符串df$start并且df$end一直给我带来麻烦.
我一直用温和的成功:apply(df, 1, function(i) seq(as.numeric(i["start"]), as.numeric(i["end"])))这我可以再传给喜欢的东西stringr::str_pad(..., width = 3, pad = "0"),但我不知道如何巧妙地抓住区域为这些重复序列.
使用data.table您可以通过链接在一起的三个步骤来完成此操作.首先,将数据帧转换为数据表setDT.其次,将start和end列转换为数字.第三,key通过为原始数据框中的每一行创建序列来创建列,其中列中的值start作为起始值,列中的值end作为结束值.第四,key通过使用将列转换回字符,sprintf并在短于3位的数字前面添加零:
library(data.table)
cols <- names(df)[1:2]
setDT(df)[, (cols) := lapply(.SD, function(x) as.numeric(as.character(x))), .SDcols = cols
][, .(key = start:end), by = zone
][, key := sprintf('%03d',key)][]
Run Code Online (Sandbox Code Playgroud)
这使:
zone key
1: 3 005
2: 5 010
3: 5 011
4: 5 012
5: 5 013
6: 7 014
7: 7 015
8: 7 016
9: 7 017
Run Code Online (Sandbox Code Playgroud)
根据您start和end列是否是因素的特征,您应该使用as.numeric(x)或as.numeric(as.character(x)).
根据@alistaire的评论,你可以奇怪地省略该as.numeric部分.从而:
setDT(df)[, (cols) := lapply(.SD, function(x) as.character(x)), .SDcols = cols
][, .(key = start:end), by = zone
][, key := sprintf('%03d',key)][]
Run Code Online (Sandbox Code Playgroud)
会给你相同的结果(当你start和end列已经是字符类时,你可以忽略该lapply步骤).