Reputation: 841
I have a data frame with one field consisting of a sequence of numbers:
test <- data.frame(N=c(1,2,3,5,7,8,9,11,13,14,15))
> test
N
1 1
2 2
3 3
4 5
5 7
6 8
7 9
8 11
9 13
10 14
11 15
N
contains a sequence of integers in ascending orderN
sometimes skips some numbers, such as 2,3,5
(4 is missing).I need to convert it into the following text format:
1-3,5,7-9,
11,13-15
This file is not data frame, but just a simple text file which contains the following conditions:
-
, i.e., 1,2,3
should be 1-3
and 1,2,3,5,6
should be 1-3,5,6
,
(no space needed)Currently I just could convert the data frame into a sequence of numbers, but the output is surrounded by c()
, consecutive numbers cannot be shortened without line breaks.
> tapply(test, (seq_along(test)-1)%/%3, paste, collapse=", ")
0
"c(1, 2, 3, 5, 7, 8, 9, 11, 13, 14, 15)"
I appreciate your idea to make it!! Thank you in advance for your support.
Upvotes: 1
Views: 101
Reputation: 15143
I'll say v
as a vector.
v <- c(1,2,3,5,7,8,9,11,13,14,15)
then split v into consecutive sets
vv <- split(v, cumsum(c(1, diff(v) != 1)))
vv
$`1`
[1] 1 2 3
$`2`
[1] 5
$`3`
[1] 7 8 9
$`4`
[1] 11
$`5`
[1] 13 14 15
Finally, transform to form you want
lapply(vv, function(x) {
if (length(x) == 1) {
x
} else(
paste0(x[1], "-", tail(x, n=1))
)
}) %>% unlist %>% as.vector
[1] "1-3" "5" "7-9" "11" "13-15"
Upvotes: 3
Reputation: 389235
Here's a possible solution using dplyr
-
library(dplyr)
output <- test %>%
#Create groups to collapse consecutive numbers
group_by(grp = cumsum(c(TRUE, diff(N) > 1))) %>%
#If more than 1 number in a group paste first and last value
summarise(text = if(n() > 1) paste0(range(N), collapse = '-') else as.character(N)) %>%
#For each 3 groups collapse the ranges as one string
group_by(line_num = ceiling(row_number()/3)) %>%
summarise(text = toString(text))
output
# line_num text
# <dbl> <chr>
#1 1 1-3, 5, 7-9
#2 2 11, 13-15
#Write the output
cat(paste0(output$text, collapse = '\n'), file = 'output.txt')
The output text file looks like -
Upvotes: 3