Home > Back-end >  How to mutate row-wise and replace first 'n' values with 0
How to mutate row-wise and replace first 'n' values with 0

Time:10-05

I'm trying to build a measurement tracker form. I'd like to populate 0 into the "Measurement" columns for each row, based on the Quantity value for that row. (For Quantity = 2, first 2 measurements = 0, the rest of the row = NA). (For Quantity = 4, all measurements = 0).

I'm wondering how to mutate these rows and replace with the proper number of 0s in the correctly indexed positions, like so:

 Feature Tool MIN MAX Quantity Measurement_1 Measurement_2 Measurement_3 Measurement_4
1       a    m 0.5 1.0        2             0             0            NA            NA
2       b    n 0.4 1.2        4             0             0             0             0

The sample code to generate the dataframe is here:

#sample data
A1 <- data.frame(Feature = c("a","b"), Tool = c("m","n"), MIN = c(0.5,0.4), MAX = c(1.0,1.2), Quantity = c(2,4))  

# Create empty data frame of NA
df <- data.frame(matrix(NA,    
                          nrow = 1,
                          ncol = max(A1$Quantity)))

#create list of sequential measurements based on maximum quantity of measurements
M <- c(sprintf("Measurement_d", seq(1,max(A1$Quantity)))) 

#set column names to these measurements
colnames(df) <- M  

#combine sample data with measurements
new_dat <- cbind(A1, df)  

My first attempts to accomplish this are something like this:

new_dat %>% rowwise() %>% mutate(new_dat[,6:new_dat$Quantity] <- 0)

But it's clear I'm missing something here.

Thanks!

CodePudding user response:

A vectorized approach in base R would be using row/column indexing. Create a matrix with row index replicated and the column index for each rows, and then do the assignment

j1 <- grep("Measurement", names(new_dat))
new_dat[cbind(rep(seq_len(nrow(new_dat)), new_dat$Quantity),
         j1[sequence(new_dat$Quantity)])] <- 0

-output

> new_dat
  Feature Tool MIN MAX Quantity Measurement_1 Measurement_2 Measurement_3 Measurement_4
1       a    m 0.5 1.0        2             0             0            NA            NA
2       b    n 0.4 1.2        4             0             0             0             0

Or with dplyr, we could do

library(dplyr)
new_dat %>% 
  mutate(across(starts_with("Measurement"),
    ~ replace(.x, readr::parse_number(cur_column()) <= Quantity, 0)))

-output

  Feature Tool MIN MAX Quantity Measurement_1 Measurement_2 Measurement_3 Measurement_4
1       a    m 0.5 1.0        2             0             0            NA            NA
2       b    n 0.4 1.2        4             0             0             0             0
  • Related