Search code examples
rdata-extraction

How to replace column values based on a condition in R


I have a data set of different orders and the quantity of that order for customers. I want to remove ordertype == "cap" from all the rows and the corresponding quantity for that order form the respective quantity column and replace it with the next values that does not correspond to "cap"

#INPUT DATA 

custID <- data.frame(c(1,2,3,4,5))
OrderType_1 <- data.frame(c("ball", "pen", "ball", "shuttle", "pen"))
OrderType_2 <- data.frame(c("pen", NA, "cap", "cap", "pen"))
OrderType_3 <- data.frame(c("cap", NA, "cap", "cap", NA))
OrderType_4 <- data.frame(c("shuttle", NA, "ball", "cap", NA))
OrderType_5 <- data.frame(c("pen", NA, "cap", "ball", NA))
QUANTITY_1 <- data.frame(c(2,3,4,5,6))
QUANTITY_2 <- data.frame(c(2, NA, 1, 3, 3))
QUANTITY_3 <- data.frame(c(3,NA,5,6,NA))
QUANTITY_4 <- data.frame(c(2,NA,3,5,NA))
QUANTITY_5 <- data.frame(c(2,NA,2,3, NA))

report <- cbind(custID, OrderType_1, OrderType_2, OrderType_3, OrderType_4, 
OrderType_5, QUANTITY_1, QUANTITY_2, QUANTITY_3, QUANTITY_4, QUANTITY_5 )
report <- as.data.frame(report)

colnames(report) <- c("CustID", "OrderType_1", "OrderType_2", "OrderType_3", 
"OrderType_4", "OrderType_5", "QUANTITY_1", "QUANTITY_2", "QUANTITY_3", 
"QUANTITY_4", "QUNATITY_5")

This is how the output should look after removing "cap" and the corresponding quantity value..

#OUTPUT DATA TYPE

custID <- data.frame(c(1,2,3,4,5))
OrderType_1 <- data.frame(c("ball", "pen", "ball", "shuttle", "pen"))
OrderType_2 <- data.frame(c("pen", NA, "ball", "ball", "pen"))
OrderType_3 <- data.frame(c("shuttle", NA, NA, NA, NA))
OrderType_4 <- data.frame(c("pen", NA, NA, NA, NA))
OrderType_5 <- data.frame(c(NA, NA, NA, NA, NA))
QUANTITY_1 <- data.frame(c(2,3,4,5,6))
QUANTITY_2 <- data.frame(c(2, NA, 3, 3, 3))
QUANTITY_3 <- data.frame(c(2,NA,NA,NA,NA))
QUANTITY_4 <- data.frame(c(2, NA,NA,5,NA))
QUANTITY_5 <- data.frame(c(NA,NA,NA,NA,NA))

report_1 <- cbind(custID, OrderType_1, OrderType_2, OrderType_3, 
OrderType_4, OrderType_5, QUANTITY_1, QUANTITY_2, QUANTITY_3, QUANTITY_4, 
QUANTITY_5 )
report_1 <- as.data.frame(report_1)

colnames(report_1) <- c("CustID", "OrderType_1", "OrderType_2", 
"OrderType_3", 
"OrderType_4", "OrderType_5", "QUANTITY_1", "QUANTITY_2", "QUANTITY_3", 
"QUANTITY_4", "QUNATITY_5")

Solution

  • Maybe using tidyverse you could approach it this way:

    This data is easier to manipulate in long form using pivot_longer. You can filter out the rows you don't want (removing both the OrderType as well as the QUANTITY). Then pivot_wider if that is the desired format, filling in NA as needed). I hope this is helpful.

    Edit: For each CustID I needed to reorder after filtering out unwanted orders.

    library(tidyverse)
    
    report %>%
      pivot_longer(cols = -CustID, 
                   names_to = c(".value", "order"),
                   names_sep = "_") %>%
      filter(OrderType != "cap") %>%
      group_by(CustID) %>%
      mutate(neworder = row_number()) %>%
      pivot_wider(id_cols = CustID, 
                  names_from = c(neworder, neworder), 
                  names_sep = "_", 
                  values_from = c(OrderType, QUANTITY))
    
    # A tibble: 5 x 9
    # Groups:   CustID [5]
      CustID OrderType_1 OrderType_2 OrderType_3 OrderType_4 QUANTITY_1 QUANTITY_2 QUANTITY_3 QUANTITY_4
       <dbl> <fct>       <fct>       <fct>       <fct>            <dbl>      <dbl>      <dbl>      <dbl>
    1      1 ball        pen         shuttle     pen                  2          2          2          2
    2      2 pen         NA          NA          NA                   3         NA         NA         NA
    3      3 ball        ball        NA          NA                   4          3         NA         NA
    4      4 shuttle     ball        NA          NA                   5          3         NA         NA
    5      5 pen         pen         NA          NA                   6          3         NA         NA