Reputation: 441
I have a data frame like this
Letter Number1 Number2 Number3 Type
A 4 5 3 10
B 10 22 24 20
C 50 24 100 30
D 60 32 12 40
Where I would like to use mutate_each to divide number1, number2, and number3 by 2, and not do anything to Letter and type. Is there an easy day to do this?
This is what I would want the final DF to look like
Letter Number1 Number2 Number3 Type
A 2 2.5 1.5 10
B 5 11 12 20
C 25 12 50 30
D 30 16 6 40
Thanks!
Upvotes: 2
Views: 3393
Reputation: 887163
We can select the 'Number' columns using starts_with
or matches
and divide those columns by 2.
library(dplyr)
mutate_each(df1, funs(./2), starts_with('Number'))
# Letter Number1 Number2 Number3 Type
#1 A 2 2.5 1.5 10
#2 B 5 11.0 12.0 20
#3 C 25 12.0 50.0 30
#4 D 30 16.0 6.0 40
As @Cotton.Rockwood suggested in the comments, in the newer versions of dplyr
(0.7.6
), we can use mutate_at
(for changing a subset of columns) or mutate_all
(to change all the columns)
df1 %>%
mutate_at(vars(starts_with("Number")), funs(./2))
Or using data.table
, we convert the 'data.frame' to 'data.table' (setDT(df1)
), get the column names that start with 'Number' ('nm1'), assign the 'nm1' with the new value ie. after dividing by '2'.
library(data.table)#v1.9.4+
setDT(df1)
nm1 <- grep('^Number', names(df1), value=TRUE)
df1[, (nm1):= lapply(.SD, `/`, 2), .SDcols=nm1]
Or a more efficient method with data.table
for multiple columns would be using set
.
for(j in nm1){
set(df1, i=NULL, j=j, value=df1[[j]]/2)
}
df1 <- structure(list(Letter = c("A", "B", "C", "D"), Number1 = c(4L,
10L, 50L, 60L), Number2 = c(5L, 22L, 24L, 32L), Number3 = c(3L,
24L, 100L, 12L), Type = c(10L, 20L, 30L, 40L)), .Names = c("Letter",
"Number1", "Number2", "Number3", "Type"), class = "data.frame",
row.names = c(NA, -4L))
Upvotes: 6
Reputation: 11
library(dplyr)
Create the test dataframe
letter <- c("A", "B", "C", "D")
n1 <- c(4, 10, 50, 60)
n2 <- c(5, 22, 24, 32)
n3 <- c(3, 24, 100, 12)
type <- c(10, 20, 30, 40)
df <- data.frame(letter, n1, n2, n3, type)
The dataframe df:
# letter n1 n2 n3 type
# 1 A 4 5 3 10
# 2 B 10 22 24 20
# 3 C 50 24 100 30
# 4 D 60 32 12 40
Make your own function
mydivide <- function(x){x/2}
Use funs() to tell mutate what function to use.
Use the '-' to tell mutate not to mutate columns 'letter' and 'type'
df <- mutate_each(df, funs(mydivide), -letter, -type)
The end result:
# letter n1 n2 n3 type
# 1 A 2 2.5 1.5 10
# 2 B 5 11.0 12.0 20
# 3 C 25 12.0 50.0 30
# 4 D 30 16.0 6.0 40
Upvotes: 1
Reputation: 31171
A base R
solution in case:
indx <- grepl("Number", names(df))
df[indx] <- df[indx]/2L
#>df
# Letter Number1 Number2 Number3 Type
#1 A 2 2.5 1.5 10
#2 B 5 11.0 12.0 20
#3 C 25 12.0 50.0 30
#4 D 30 16.0 6.0 40
Upvotes: 4