Reputation: 111
I have the following df
, where: Name
displays the concept to pay for and Code
the number of times Name
must be repeated in order to optimize processes. Initially it looks like this:
Name Code
Tax 1
Gas 2
Tax 1
Gas 2
Tax 1
Lunch 2
Tax 1
Car 2
df = data.frame(Name = c('Tax', 'Gas', 'Tax', 'Gas', 'Tax', 'Lunch', 'Tax', 'Car'),
Code = rep(c(1,2)))
After repeating Gas
, Lunch
and Car
twice, it looks like this:
Name Code
Tax 1
Gas 2
Gas 2
Tax 1
Gas 2
Gas 2
Tax 1
Lunch 2
Lunch 2
Tax 1
Car 2
Car 2
df = df[rep(seq_len(nrow(df)), df$Code),]
What I'd like to do is to reorder the rows to make my df
look like this, where df
is just sorted by Code
in this manner 2
, 1
, 2
(each Tax
and Gas
, Tax
and Lunch
, Tax
and Car
are one group):
Is there a way to do so without any libraries? Since the final script will not be used just for me but also for r newbies at work.
I already tried with:
df[order(factor(df$Code, levels = c(2,1,2))),]
and also adding row.names
as column to match
like this: df[order(df$Code, df$row.names),]
but it does not seem to work as expected.
Also tried with this and this answers but could not succeed.
Upvotes: 1
Views: 283
Reputation: 887981
We can do this in base R
i1 <- with(df, ave(seq_len(nrow(df)), as.integer(gl(nrow(df), 3,
nrow(df))), FUN = function(i) c(i[c(2, 1, 3)])))
out <- df[i1,]
row.names(out) <- NULL
out
# Name Code
#1 Gas 2
#2 Tax 1
#3 Gas 2
#4 Gas 2
#5 Tax 1
#6 Gas 2
#7 Lunch 2
#8 Tax 1
#9 Lunch 2
#10 Car 2
#11 Tax 1
#12 Car 2
Or with tidyverse
library(tidyverse)
df %>% # initial dataset
uncount(Code, .remove = FALSE) %>%
mutate(rn = row_number()) %>%
group_by(grp = gl(n(), 3, n())) %>%
slice(c(2, 1, 3)) %>%
ungroup %>%
select(-rn, -grp)
Upvotes: 1
Reputation: 56
This works perfectly, assuming I understood the logic behind your sorting.
df = data.frame(Name = c('Tax', 'Gas', 'Tax', 'Gas', 'Tax', 'Lunch', 'Tax', 'Car'),
Code = rep(c(1,2)))
df = df[rep(seq_len(nrow(df)), df$Code),]
vect<-c()
for (i in 1:nrow(df)){
if ((i+1)%%3==0)
vect<-c(vect,i,i-1,i+1)
}
df<-df[vect,]
rownames(df)<-NULL
Upvotes: 1