Oscar Kjell
Oscar Kjell

Reputation: 1651

In R subtract a vector from each row of a dataframe

I'm searching a better, more efficient solution to subtract a vector from each row of a dataframe (df1). My current solution repeats the vector (Vec) to create a dataframe (Vec_df1) with similar length as the df1 and then subtracts the two dataframes. Now I wonder if there is a more "direct" way to do this without having to create the new Vec_df1 dataframe (preferably in tidyverse). See example data below.

#Example data
V1 <- c(1, 2, 3)
V2 <- c(4, 5, 6)
V3 <- c(7, 8, 9)

df1 <- tibble(V1, V2, V3)
Vec <- c(1, 1, 2)

# Current solution, creates a dataframe with the same nrows by repeating the vector. 
Vec_df1 <- tibble::as_tibble(t(Vec)) %>%
  dplyr::slice(rep(dplyr::row_number(), nrow(df1)))

# Subtraction. 
df2 <- df1-Vec_df1
df2

Thanks in advance

Upvotes: 1

Views: 1571

Answers (4)

akrun
akrun

Reputation: 886998

We can also do

df1 - Vec[col(df1)]

Upvotes: 1

Onyambu
Onyambu

Reputation: 79208

the fastest way to do this :

as_tibble(t(t(df1) - Vec))

# A tibble: 3 x 3
     V1    V2    V3
  <dbl> <dbl> <dbl>
1     0     3     5
2     1     4     6
3     2     5     7

Upvotes: 2

lroha
lroha

Reputation: 34406

A similar approach using map2_df():

library(purrr)

map2_df(df1, Vec, `-`)

# A tibble: 3 x 3
     V1    V2    V3
  <dbl> <dbl> <dbl>
1     0     3     5
2     1     4     6
3     2     5     7

Upvotes: 4

Ronak Shah
Ronak Shah

Reputation: 388862

We can use sweep :

sweep(df1, 2, Vec, `-`)
# `-` is default FUN in sweep so you can also use
#sweep(df1, 2, Vec)

#  V1 V2 V3
#1  0  3  5
#2  1  4  6
#3  2  5  7

Or an attempt similar to yours

df1 - rep(Vec, each = nrow(df1))

Upvotes: 4

Related Questions