slinel
slinel

Reputation: 61

replace certain values of multiple vectors

I have a dataset with multiple 0/1 vectors. For every value = 1, I'd like this value to be replaced by a value of another vector with different content. A testdataset would look like this.

name <- c("tim", "tom", "ben", "mary", "jane")
sex <- c("male","male","male","female","female")
jahr <- c(1985, 1986, 1985, 1986, 1984)
v4 <- c(1,0,1,0,1)
v5 <- c(0,0,0,0,1)
v6 <- c(1,0,0,1,1)
v7 <- c(0,0,0,0,0)
df <- data.frame(name, sex, born, v4,v5,v6,v7)

The function I've written looks like this:

  df[2,5] <- df[1,"v4"]
  yearset <- function(x) {
                for (i in 1:ncol(x)) {          #jede Spalte
                  for (j in 1:nrow(x)) {        #jede Zeile
                    if (x[j,i] == 1) {          # wenn Wert = 1
                      x[j,i] <- x[j,"jahr"]     # ersetze durch Wert
                      print(paste("column/variable", i, "and row ", j))
                      } 
                  }
                }
  }

Problem: nothing happens. I receive no errors, the IF-loops seem to be correct (as shown by the print command) and the functionality of recode-command has been tested just before. What am I missing?

Upvotes: 0

Views: 104

Answers (4)

Allan Cameron
Allan Cameron

Reputation: 174506

Are you looking for this?

df[4:7] <- lapply(df[4:7], function(x) ifelse(x == 1, df$born, x))

df
#>   name    sex born   v4   v5   v6 v7
#> 1  tim   male 1985 1985    0 1985  0
#> 2  tom   male 1986    0    0    0  0
#> 3  ben   male 1985 1985    0    0  0
#> 4 mary female 1986    0    0 1986  0
#> 5 jane female 1984 1984 1984 1984  0

EDIT

If you want to be able to select the correct columns programatically, you can find the subset of columns that match your criteria (here, for example you want all columns that are numeric, except the born column, so you can select only those columns that are numeric and have a maximum value of 1):

num_cols <- sapply(df, function(x) if(!is.numeric(x)) FALSE else max(x) < 2)
df[num_cols] <- lapply(df[num_cols], function(x) ifelse(x == 1, df$born, x))

df
#>   name    sex born   v4   v5   v6 v7
#> 1  tim   male 1985 1985    0 1985  0
#> 2  tom   male 1986    0    0    0  0
#> 3  ben   male 1985 1985    0    0  0
#> 4 mary female 1986    0    0 1986  0
#> 5 jane female 1984 1984 1984 1984  0

Upvotes: 3

akrun
akrun

Reputation: 887891

We can use sweep from base R

df[-(1:3)] <-  sweep(df[-(1:3)], 1, df$born, `*`)

Upvotes: 0

ThomasIsCoding
ThomasIsCoding

Reputation: 102710

Try the code below

df[-(1:3)] <- df$born * df[-(1:3)]

or

ids <- startsWith(names(df), "v")
df[ids] <- df$born * df[ids]

giving

> df
  name    sex born   v4   v5   v6 v7
1  tim   male 1985 1985    0 1985  0
2  tom   male 1986    0    0    0  0
3  ben   male 1985 1985    0    0  0
4 mary female 1986    0    0 1986  0
5 jane female 1984 1984 1984 1984  0

Upvotes: 2

Gregor Thomas
Gregor Thomas

Reputation: 146164

Another simplification, this one using multiplication:

cols = paste0("v", 4:7)
df[cols] = df[cols] * df$born
df
#   name    sex born   v4   v5   v6 v7
# 1  tim   male 1985 1985    0 1985  0
# 2  tom   male 1986    0    0    0  0
# 3  ben   male 1985 1985    0    0  0
# 4 mary female 1986    0    0 1986  0
# 5 jane female 1984 1984 1984 1984  0

Upvotes: 2

Related Questions