0

I am basically working off of this answer, but want to add one more wrinkle I can't figure out. I want to multiple all columns contained in a list by the weight column, similar to the example below:

#df 1
Id = c("1", "2", "3", "4")
Persons = c(300, 400, 200, 5000)
Houses = c(20, 40, 10, 23)
Ages =  c(45, 34, 50, 44)
Races = c(1, 3, 1, 2)
weight = c(0.9, 1.2, 0.8, 1.1)

estimates = data.frame(Id, Persons, Houses, Ages, Races, weight)
list <- as.list(colnames(subset(estimates, select = -c(Id, weight))))
estimates <- estimates %>% mutate_each(funs(.*weight), . %in% list)

But I keep getting the following error:

Error in as_indices_impl(): ! Must subset columns with a valid subscript vector. ✖ Subscript has the wrong type logical. ℹ It must be numeric or character.

tchoup
  • 971
  • 4
  • 11
  • Why would you put column names in a `list` instead of keeping them as a character vector? – Gregor Thomas Nov 17 '22 at 21:01
  • The difference between a `list` and an atomic vector is that a `list` can contain elements of different classes - the first element can be a data frame, the second a numeric vector, the third a model object, and the fourth a character vector. Column names are character vector, there's no need to turn them into a `list` unless you're mixing them with other object types. – Gregor Thomas Nov 17 '22 at 21:09

1 Answers1

1

Using the modern across() instead of the deprecated mutate_each():

estimates %>% mutate(across(all_of(unlist(list)), \(x) x * weight))

Or with base R:

estimates[unlist(list)] <- estimates[unlist(list)] * estimate$weight

Of course, if you simplify your definition keeping it a character vector, then you can use cols instead of unlist(list).

cols = setdiff(names(estimtes), c("Id", "weight"))

Or, with across() you can skip the list definition entirely:

estimates %>% mutate(across(!c(Id, weight), \(x) x * weight))
Gregor Thomas
  • 136,190
  • 20
  • 167
  • 294