Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

add row based on variable condition in R

Tags:

r

I have df as follow

df
ID   type  other-col
1    A1      cc
1    A2      dd
1    A3      cc
2    A1      cc
2    B1      aa
3    A2      aa

I want add new to when "ID" changes with the value of F for "type" and "other-col" columns

new_df
ID
  df
    ID   type  other-col
    1    A1      cc
    1    A2      dd
    1    A3      cc
    1    F       F     <- this row added
    2    A1      cc
    2    B1      aa
    2    F       F      <- this row added
    3    A2      aa

how can I do it in R? thx

like image 248
Cina Avatar asked Dec 05 '22 09:12

Cina


2 Answers

This should be doable in a single replacement operation once you know the indexes of where each change occurs. E.g.:

idx <- match(unique(df$ID), df$ID)[-1] - 1

df <- df[sort(c(sequence(nrow(df)),idx)),]
df[seq_along(idx) + idx, c("type","other_col")] <- "F"

#    ID type other_col
#1    1   A1        cc
#2    1   A2        dd
#3    1   A3        cc
#3.1  1    F         F
#4    2   A1        cc
#5    2   B1        aa
#5.1  2    F         F
#6    3   A2        aa

Where df was:

df <- read.table(text="ID   type  other_col
1    A1      cc
1    A2      dd
1    A3      cc
2    A1      cc
2    B1      aa
3    A2      aa", header=TRUE, stringsAsFactors=FALSE)
like image 175
thelatemail Avatar answered Dec 25 '22 23:12

thelatemail


An option with group_split and add_row. We can split by 'ID' with group_split into a list of data.frames, then loop through the list with map, add a row as the last row (add_row - by default adds row to the end, but we can control it with .before and .after), then slice out the last row as the last 'ID' didn't need the 'F' row

library(tidyverse)
df1 %>%
   group_split(ID) %>% 
   map_dfr(~ .x %>% 
               add_row(ID = first(.$ID), type = 'F', `other-col` = 'F'))  %>%
   slice(-n())
like image 36
akrun Avatar answered Dec 26 '22 00:12

akrun