重复3位字符序列的行值 - 整洁的数据

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"),但我不知道如何巧妙地抓住区域为这些重复序列.

Jaa*_*aap 5

使用data.table您可以通过链接在一起的三个步骤来完成此操作.首先,将数据帧转换为数据表setDT.其次,将startend列转换为数字.第三,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)

根据您startend列是否是因素的特征,您应该使用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)

会给你相同的结果(当你startend列已经是字符类时,你可以忽略该lapply步骤).