Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Replace values into previous row with a condition

I want to get data where ID column doesn´t start with 00 and append this value of ID column to the end of Description column in previous row.

Then replace the rest of values into after Name column in the previous row. How can I do that with R?

Here is source of dummy data: https://docs.google.com/spreadsheets/d/1SbmaM8hXck-z5nsNfDMbhwijvAGPkPPBgQ_eY4JAMC8/edit?usp=sharing

ID      Year    Description  Name   User       Factor_1  Factor_2   Factor_3
0011    2016    blue colour  AA     James      Xfac      NA         NA
is nice XXX     XLM          Yfac   different  Yfac      NA         NA
0024    2017    red colour   DD     Mark       Zfac      NA         NA
is good YYY     STM          Lfac   unique     Zfac      NA         NA

What I want to have:

ID      Year    Description          Name   User  Factor_1   Factor_2   Factor_3
0011    2016    blue colour is nice  XXX    XLM   Yfac       different  Yfac
0024    2017    red colour is good   YYY    STM   Lfac       unique     Zfac
like image 913
kimi_f109 Avatar asked Jul 04 '26 04:07

kimi_f109


2 Answers

There's the first part where you want to paste the descriptions together,
and there's the part where you want to move your variables as well, as you want "XXX" and "YYY" in your "user" column.

Also, in Viveks answer all wrong lines are pasted with ALL "right" lines, which works in your example, but not if you have a few right lines, and then a wrong one. Working with booleans (TRUE/FALSE) sometimes works fine, but in this case, I think you want to use an integer index, as that makes it easier to refer to "the previous line". Which gives me code:

rmlines <- which(!substr(df$ID,1,2)=="00")
df$Description[rmlines-1] <- paste(df$Description[rmlines-1], df[rmlines,1], sep=" ")
df[rmlines-1, 4:8] <- df[rmlines, 2:6]
df <- df[-rmlines,]

But there's one more problem to consider: what classes are your columns?
When I tried it out, I treated everything as a character, which means you can move columns around fine. In your data, some may be factors or something else, so you might want to change the classes. I think it's easiest to first change it all to character, and then change it (back) to the final class you want your columns to be.

# To change everything to character:
df <- as.data.frame(lapply(df, as.character), stringsAsFactors = FALSE)
# And to assign the right classes, you need to decide case-by-case:
df$Year <- as.integer(df$Year)
df$Factor_1 <- as.factor(df$Factor1) # Optionally provide levels
like image 164
Emil Bode Avatar answered Jul 05 '26 19:07

Emil Bode


Here's a solution with dplyr:

library(dplyr)

df %>% 
  bind_cols(df %>% rename_all(function(x) paste0(x, "_dummy"))) %>%
  mutate(
    Description = ifelse(substr(lead(ID), 1, 2) != "00", 
                         paste(Description, lead(ID)), Description),
    Name = lead(Year_dummy),
    User = lead(Description_dummy),
    Factor_1 = lead(Name_dummy),
    Factor_2 = lead(User_dummy),
    Factor_3 = lead(Factor_1_dummy)
  ) %>% select(-ends_with("dummy")) %>%
  filter(substr(ID, 1, 2) == "00")

Output:

    ID Year       Description Name User Factor_1  Factor_2 Factor_3
1 0011 2016 blue colour is nice  XXX  XLM     Yfac different     Yfac
2 0024 2017  red colour is good  YYY  STM     Lfac    unique     Zfac

In case you're dealing with a large number of columns, a combination of dplyr and base R could do it:

library(dplyr)

df_combo <- cbind(df, df)

df$Description <- ifelse(substr(lead(df$ID), 1, 2) != "00", 
                               paste(df$Description, lead(df$ID)), df$Description)

for (i in (ncol(df) + 4):ncol(df_combo)) {

  df_combo[[i]] <- lead(df_combo[[i - ncol(df) - 2]])

}

df_combo <- subset(df_combo, substr(ID, 1, 2) == "00")

df_descr <- subset(df, substr(ID, 1, 2) == "00")

df_final <- df_combo[, (ncol(df) + 1):ncol(df_combo)]

df_final$Description <- df_descr$Description

rm(df_descr, df_combo)

Output:

     ID Year       Description Name User Factor_1  Factor_2 Factor_3
1: 0011 2016 blue colour is nice  XXX  XLM     Yfac different     Yfac
2: 0024 2017  red colour is good  YYY  STM     Lfac    unique     Zfac
like image 40
arg0naut91 Avatar answered Jul 05 '26 17:07

arg0naut91



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!