I have a list of several data frames and as the heading states, would like to add a new row (where column Z is "VALUE1") in the end of data frame if the last actual value/string (not counting NA "values") of column Z doesn't contain "VALUE1". I already have a script for adding a new row into the beginning of df if the first value of column Z doesn't contain "VALUE1", but can't quite modify the script into the new one myself.
The aforementioned script I'd like to modify looks following:
for(i in 1:length(df)){
df[[i]] <- df[[i]] %>%
filter(!is.na(Z)) %>%
slice(1) %>%
mutate(across(col1:col3, ~ 0)) %>%
filter(!grepl("VALUE1", Z)) %>%
mutate(Z = "VALUE1") %>%
bind_rows(., df[[i]])
}
Also if possible, it would be very much welcome if there could be a short comment for each line explaining what happens in the code (not necessary tho) for further learning and understanding. Thank you!
CodePudding user response:
It's a quite strange script.
To add a line at end of df's if last is VALUE1, slice by n()
instead of by 1
, and flip order of bind_rows
arguments. Try this:
for(i in 1:length(df)){
df[[i]] <- df[[i]] %>%
filter(!is.na(Z)) %>% #filter those rows that are not NA
slice(n()) %>% # select the last (n()) row (in original, select first) we have a new df with 1 row
mutate(across(col1:col3, ~ 0)) %>% # set all to zero (since it will be used as new row)
filter(!grepl("VALUE1", Z)) %>% # if Z contains VALUE1 the result is a df with 0 row (filter out)
mutate(Z = "VALUE1") %>% # set Z to value1 (if df contains 1 row)
bind_rows(df[[i]],.) # paste the new row (. is the pipe placeholder) at end of original data.frame (df[[i]]).
}
# if the step filter(!grepl("VALUE1", Z)) filtered out the row, then bind_rows append a zero row
# dataframe and the effect is that df[[i]] does not change at all.