Looping through rows and columns in R does not work - r

I am just trying to fill gaps but in a loop. It is a monthly data, and fill_gaps produces NAs for every day. I am not sure why.
for (x in 2:length(differencing)){
for(micky in 1:length(differencing$`d_ BA`)){
if(is.na(differencing[micky,x])== T){
differencing[micky,x] = differencing[micky-1,x]
}
}
}
here is the error that I am getting:
Error: Assigned data `differencing[(micky - 1), x]` must be compatible with row subscript `micky`.
x 1 row must be assigned.
x Assigned data has 0 rows.
i Row updates require a list value. Do you need `list()` or `as.list()`?
Run `rlang::last_error()` to see where the error occurred.

This can be easily done using fill
library(tidyr)
library(dplyr)
differencing %>%
fill(everything())
Or we can use na.locf from zoo
library(zoo)
na.locf(differencing)
In the OP's loop, in the first line, it would be
for (x in 2:length(differencing$`d_ BA`)
...
as length of a data.frame will be the number of columns (as mentioned in the comments) and is different from length of a column i.e. vector
As the OP mentioned none of them works (OP didn't provide any example), using a small reproducible example ('tmp')
tmp %>%
fill(everything())
# mpg cyl disp hp drat wt qsec vs am gear carb
#Mazda RX4 21.0 6 160 110 3.90 2.620 16.46 0 1 4 4
#Mazda RX4 Wag 21.0 6 160 110 3.90 2.875 17.02 0 1 4 4
#Datsun 710 22.8 4 108 93 3.85 2.320 18.61 1 1 4 1
#Hornet 4 Drive 21.4 6 258 110 3.08 3.215 19.44 1 0 3 1
#Hornet Sportabout 18.7 6 258 110 3.15 3.440 17.02 0 0 3 2
#Valiant 18.1 6 258 110 2.76 3.460 20.22 1 0 3 1
or using na.locf
na.locf(tmp)
# mpg cyl disp hp drat wt qsec vs am gear carb
#Mazda RX4 21.0 6 160 110 3.90 2.620 16.46 0 1 4 4
#Mazda RX4 Wag 21.0 6 160 110 3.90 2.875 17.02 0 1 4 4
#Datsun 710 22.8 4 108 93 3.85 2.320 18.61 1 1 4 1
#Hornet 4 Drive 21.4 6 258 110 3.08 3.215 19.44 1 0 3 1
#Hornet Sportabout 18.7 6 258 110 3.15 3.440 17.02 0 0 3 2
#Valiant 18.1 6 258 110 2.76 3.460 20.22 1 0 3 1
data
tmp <- head(mtcars)
tmp[c(2, 5, 6), c(3, 4, 2)] <- NA

Related

Replace all other values in R

I have a column including lots of "0" and other values (f.i. 2 or 2,3 etc). Is there any possibility to rename the columns with 0 to "None" and all other values to "others"? I wanted to use fct_recode or fct_collapse but cant figure out how to include all other values. Do you have any idea? I must not be necessarily include the fct_recode function.
Thanks a lot
Philipp
I tried to use fct_recode, fct_collapse
Here is a way to do it using mtcars and the vs column as an example:
cars <- mtcars
head(cars)
mpg cyl disp hp drat wt qsec vs am gear carb
Mazda RX4 21.0 6 160 110 3.90 2.620 16.46 0 1 4 4
Mazda RX4 Wag 21.0 6 160 110 3.90 2.875 17.02 0 1 4 4
Datsun 710 22.8 4 108 93 3.85 2.320 18.61 1 1 4 1
Hornet 4 Drive 21.4 6 258 110 3.08 3.215 19.44 1 0 3 1
Hornet Sportabout 18.7 8 360 175 3.15 3.440 17.02 0 0 3 2
Valiant 18.1 6 225 105 2.76 3.460 20.22 1 0 3 1
cars$vs <- ifelse(cars$vs == 0, "none", "other")
head(cars)
mpg cyl disp hp drat wt qsec vs am gear carb
Mazda RX4 21.0 6 160 110 3.90 2.620 16.46 none 1 4 4
Mazda RX4 Wag 21.0 6 160 110 3.90 2.875 17.02 none 1 4 4
Datsun 710 22.8 4 108 93 3.85 2.320 18.61 other 1 4 1
Hornet 4 Drive 21.4 6 258 110 3.08 3.215 19.44 other 0 3 1
Hornet Sportabout 18.7 8 360 175 3.15 3.440 17.02 none 0 3 2
Valiant 18.1 6 225 105 2.76 3.460 20.22 other 0 3 1
Note that R coerces the vs column from numeric to character. But you could do that explicitly first for clarity:
cars$vs <- as.character(cars$vs)
Using dplyr, we can do this on multiple colums as
library(dplyr)
df1 <- df1 %>%
mutate(across(everything(), ~ case_when(.x == 0 ~ "none", TRUE ~ "other")))
Or in base R
df1[] <- c("other", "none")[1 + (df1 == 0)]

Re-order dataframe columns in R

I need to re-ordering the columns' position in a dataframe with 500 columns. In fact, I only want the last column to be moved between the third and the fourth columns.
Here is what I tried:
df[ ,c(1, 2, 3, ncol(df), 4:ncol(df)-1)]
But it gives me a vector of values which are the columns' number. Would you someone tell me what I expect wrong from this code?
The issue maybe related to the operator precedence - wrap the (ncol(df)-1) within bracket (assuming the original object is a data.frame)
library(data.table)
df <- df[ ,c(1, 2, 3, ncol(df), 4:(ncol(df)-1)), with = FALSE]
Or use setcolorder to update the original object
setcolorder(df, c(1, 2, 3, ncol(df), 4:(ncol(df)-1)))
NOTE: with = FALSE was added after the OP confirmed it is a data.table object
Or another option is select
library(dplyr)
df <- df %>%
select(1:3, last_col(), everything())
Or with relocate
df <- df %>%
relocate(last_col(), .before = 4)
-reproducible example testing
> data(mtcars)
> head(mtcars)[, c(1, 2, 3, ncol(mtcars), 4:(ncol(mtcars)-1))]
mpg cyl disp carb hp drat wt qsec vs am gear
Mazda RX4 21.0 6 160 4 110 3.90 2.620 16.46 0 1 4
Mazda RX4 Wag 21.0 6 160 4 110 3.90 2.875 17.02 0 1 4
Datsun 710 22.8 4 108 1 93 3.85 2.320 18.61 1 1 4
Hornet 4 Drive 21.4 6 258 1 110 3.08 3.215 19.44 1 0 3
Hornet Sportabout 18.7 8 360 2 175 3.15 3.440 17.02 0 0 3
Valiant 18.1 6 225 1 105 2.76 3.460 20.22 1 0 3
> head(mtcars) %>% select(1:3, last_col(), everything())
mpg cyl disp carb hp drat wt qsec vs am gear
Mazda RX4 21.0 6 160 4 110 3.90 2.620 16.46 0 1 4
Mazda RX4 Wag 21.0 6 160 4 110 3.90 2.875 17.02 0 1 4
Datsun 710 22.8 4 108 1 93 3.85 2.320 18.61 1 1 4
Hornet 4 Drive 21.4 6 258 1 110 3.08 3.215 19.44 1 0 3
Hornet Sportabout 18.7 8 360 2 175 3.15 3.440 17.02 0 0 3
Valiant 18.1 6 225 1 105 2.76 3.460 20.22 1 0 3
> ?relocate
> head(mtcars) %>% relocate(last_col(), .before = 4)
mpg cyl disp carb hp drat wt qsec vs am gear
Mazda RX4 21.0 6 160 4 110 3.90 2.620 16.46 0 1 4
Mazda RX4 Wag 21.0 6 160 4 110 3.90 2.875 17.02 0 1 4
Datsun 710 22.8 4 108 1 93 3.85 2.320 18.61 1 1 4
Hornet 4 Drive 21.4 6 258 1 110 3.08 3.215 19.44 1 0 3
Hornet Sportabout 18.7 8 360 2 175 3.15 3.440 17.02 0 0 3
Valiant 18.1 6 225 1 105 2.76 3.460 20.22 1 0 3

write r function to modify value in data frame

I have a set a variables say Var1, Var2 to Varn. They all take three possible values 0, 1, and 2. I want to replace all 2 as 1
like so
df$Var1[df$Var1 >= 1] <- 1
This does the job. But when I try to write a function to do this
MakeBinary <- function(varName dfName){dfName$varName[dfName$varNAme > = 1] <- 1}
and use this function like:
MakeBinary(Var2, df)
I got an error message: Error in $<-.data.frame(*tmp*, "varName", value = numeric(0)) :
replacement has 0 rows, data has 512.
I just want to know why I got this message. Thanks. My sample size is 512.
If we are passing column name as string, then use [[ instead of $ and return the dataset
MakeBinary <- function(varName, dfName){
dfName[[varName]][dfName[[varName]] >= 1] <- 1
dfName
}
MakeBinary("Var2", df)
example with mtcars
MakeBinary("carb", head(mtcars))
# mpg cyl disp hp drat wt qsec vs am gear carb
#Mazda RX4 21.0 6 160 110 3.90 2.620 16.46 0 1 4 1
#Mazda RX4 Wag 21.0 6 160 110 3.90 2.875 17.02 0 1 4 1
#Datsun 710 22.8 4 108 93 3.85 2.320 18.61 1 1 4 1
#Hornet 4 Drive 21.4 6 258 110 3.08 3.215 19.44 1 0 3 1
#Hornet Sportabout 18.7 8 360 175 3.15 3.440 17.02 0 0 3 1
#Valiant 18.1 6 225 105 2.76 3.460 20.22 1 0 3 1
Unquoted arguments for variable names can be passed as well, but it needs to be converted to string
MakeBinary <- function(varName, dfName){
varName <- deparse(substitute(varName))
dfName[[varName]][dfName[[varName]] >= 1] <- 1
dfName
}
MakeBinary(Var2, df)
Using a reproducible example with mtcars
MakeBinary(carb, head(mtcars))
# mpg cyl disp hp drat wt qsec vs am gear carb
#Mazda RX4 21.0 6 160 110 3.90 2.620 16.46 0 1 4 1
#Mazda RX4 Wag 21.0 6 160 110 3.90 2.875 17.02 0 1 4 1
#Datsun 710 22.8 4 108 93 3.85 2.320 18.61 1 1 4 1
#Hornet 4 Drive 21.4 6 258 110 3.08 3.215 19.44 1 0 3 1
#Hornet Sportabout 18.7 8 360 175 3.15 3.440 17.02 0 0 3 1
#Valiant 18.1 6 225 105 2.76 3.460 20.22 1 0 3 1

How to assign object to output of a function?

I'm trying to assign something to the output of Sys.Date(). For example, say I want to name the object with today's date:
format(Sys.Date(), "%b%d") <- mtcars
I get the error:
invalid (NULL) left side of assignment.
I tried:
eval(parse(text = format(Sys.Date(), "%b%d"))) <- mtcars
Gets the same error msg. What am I missing / is there a solution?
We can use assign
assign(format(Sys.Date(), "%b%d"), mtcars)
head(Sep11)
# mpg cyl disp hp drat wt qsec vs am gear carb
#Mazda RX4 21.0 6 160 110 3.90 2.620 16.46 0 1 4 4
#Mazda RX4 Wag 21.0 6 160 110 3.90 2.875 17.02 0 1 4 4
#Datsun 710 22.8 4 108 93 3.85 2.320 18.61 1 1 4 1
#Hornet 4 Drive 21.4 6 258 110 3.08 3.215 19.44 1 0 3 1
#Hornet Sportabout 18.7 8 360 175 3.15 3.440 17.02 0 0 3 2
#Valiant 18.1 6 225 105 2.76 3.460 20.22 1 0 3 1

how to swap the third column with the last column, and then delete the swapped last column in R

i want to swap a specific column with the last column, and then delete the last column after swapping. After delete ncol(testFrame) will decrease by 1
Usually a reproducible example is expected but your description is clear enough to understand what you want to do.
Using mtcars as sample data
df <- mtcars
head(df)
# mpg cyl disp hp drat wt qsec vs am gear carb
#Mazda RX4 21.0 6 160 110 3.90 2.620 16.46 0 1 4 4
#Mazda RX4 Wag 21.0 6 160 110 3.90 2.875 17.02 0 1 4 4
#Datsun 710 22.8 4 108 93 3.85 2.320 18.61 1 1 4 1
#Hornet 4 Drive 21.4 6 258 110 3.08 3.215 19.44 1 0 3 1
#Hornet Sportabout 18.7 8 360 175 3.15 3.440 17.02 0 0 3 2
#Valiant 18.1 6 225 105 2.76 3.460 20.22 1 0 3 1
swap_column <- 3
cols <- seq_len(ncol(df))
df1 <- df[replace(cols, cols == swap_column, ncol(df))][-ncol(df)]
head(df1)
# mpg cyl carb hp drat wt qsec vs am gear
#Mazda RX4 21.0 6 4 110 3.90 2.620 16.46 0 1 4
#Mazda RX4 Wag 21.0 6 4 110 3.90 2.875 17.02 0 1 4
#Datsun 710 22.8 4 1 93 3.85 2.320 18.61 1 1 4
#Hornet 4 Drive 21.4 6 1 110 3.08 3.215 19.44 1 0 3
#Hornet Sportabout 18.7 8 2 175 3.15 3.440 17.02 0 0 3
#Valiant 18.1 6 1 105 2.76 3.460 20.22 1 0 3
We replace the column number swap_column with last column number (ncol(df)) and then remove the last column (-ncol(df)).
We can do this conveniently with add_column from tibble. The .after and .before parameters can take either column index or column name. Suppose, we need to shift last column to third position
library(tibble)
data(mtcars)
df1 <- add_column(mtcars[-ncol(mtcars)], mtcars[ncol(mtcars)], .after = 2)
head(df1)
# mpg cyl carb disp hp drat wt qsec vs am gear
#Mazda RX4 21.0 6 4 160 110 3.90 2.620 16.46 0 1 4
#Mazda RX4 Wag 21.0 6 4 160 110 3.90 2.875 17.02 0 1 4
#Datsun 710 22.8 4 1 108 93 3.85 2.320 18.61 1 1 4
#Hornet 4 Drive 21.4 6 1 258 110 3.08 3.215 19.44 1 0 3
#Hornet Sportabout 18.7 8 2 360 175 3.15 3.440 17.02 0 0 3
#Valiant 18.1 6 1 225 105 2.76 3.460 20.22 1 0 3

Resources