Reputation: 669
I have a named numeric vector in R with more than 2000 named numbers. I would like to split each element, in which the number is higher than 1, into the number of elements as indicated by the number, to have in the end only the number 1. But the important thing is to have also the names changed as indicated in my output.
Input:
obj<- c(3,1,1,1,6,1,1,1,1,1,1,1,1,3)
names(obj)<- c("V4","V10","V12","V15","V16","V20","V21","V22","V23","V36","V39","V40","V41","V42")
>obj
V4 V10 V12 V15 V16 V20 V21 V22 V23 V36 V39 V40 V41 V42
3 1 1 1 6 1 1 1 1 1 1 1 1 3
Output:
obj_out<- c(1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,3)
names(obj_out)<- c("V4_1","V4_2","V4_3","V10","V12","V15","V16_1","V16_2","V16_3","V16_4","V16_5","V16_6","V20","V21","V22","V23","V36","V39","V40","V41","V42_1","V42_2","V42_3")
> obj_out
V4_1 V4_2 V4_3 V10 V12 V15 V16_1 V16_2 V16_3 V16_4 V16_5 V16_6 V20 V21
1 1 1 1 1 1 1 1 1 1 1 1 1 1
V22 V23 V36 V39 V40 V41 V42_1 V42_2 V42_3
1 1 1 1 1 1 1 1 1
I have already a code, but it names the sequence completely new, starting with V1:
obj_out<- paste0("V",rep(seq_along(obj_out), obj_out), "_", sequence(obj_out))
Upvotes: 2
Views: 202
Reputation: 39858
One option utilizing purrr
could be:
imap(obj[obj > 1], ~ set_names(rep(1, .x), paste(.y, 1:.x, sep = "_"))) %>%
reduce(c) %>%
c(., obj[obj == 1])
V4_1 V4_2 V4_3 V16_1 V16_2 V16_3 V16_4 V16_5 V16_6 V42_1 V42_2 V42_3 V10 V12
1 1 1 1 1 1 1 1 1 1 1 1 1 1
V15 V20 V21 V22 V23 V36 V39 V40 V41
1 1 1 1 1 1 1 1 1
Upvotes: 1
Reputation: 388982
Here is one base R approach :
#Repeat each value in obj, obj number of times
res <- rep(obj, obj)
#Change all values to 1.
res[] <- 1
#Change the names
names(res) <- ave(names(res), names(res), FUN = function(x)
if(length(x) == 1) x else paste(x, seq_along(x), sep = '_'))
res
# V4_1 V4_2 V4_3 V10 V12 V15 V16_1 V16_2 V16_3 V16_4 V16_5 V16_6
# 1 1 1 1 1 1 1 1 1 1 1 1
# V20 V21 V22 V23 V36 V39 V40 V41 V42_1 V42_2 V42_3
# 1 1 1 1 1 1 1 1 1 1 1
Upvotes: 2