简体   繁体   中英

Multiply each value of a dataframe by a row of another dataframe searched by id

I'm new with R and I have tried a lot to solve this problem, if anyone could help me I'd be very grateful! This is my problem:

I have two data frame (df1 and df2) and what I need is to multiply each value of df1 by a row of df2 searched by id. This is an example of what I'm looking for:

df1<-data.frame(ID=c(1,2,3), x1=c(6,3,2), x2=c(2,3,1), x3=c(4,10,7))
df1
df2<-data.frame(ID=c(1,2,3), y1=c(0.01,0.02,0.05), y2=c(0.2,0.03,0.11), y3=c(0.3,0.09,0.07))
df2

#Example of what I need
df1xdf2<- data.frame(ID=c(1,2,3), r1=c(0.06,0.06,0.1), r2=c(1.2,0.09,0.22), r3=c(1.8,0.27,0.14),
                     r4=c(0.02,0.06,0.05),r5=c(0.4,0.09,0.11),r6=c(0.6,0.27,0.07),r7=c(0.04,0.2,0.35),r8=c(0.8,0.3,0.77),r9=c(1.2,0.9,0.49))

df1xdf2

I've tried with loops by row and column but I only get a 1x1 multiplication.

My dataframes have same number of rows, columns and factor names. My real life dataframes are much larger, both rows and columns. Does anyone know how to solve it?

You could use lapply to multiply every column of df1 with complete df2 . We can cbind the dataframes together and rename the columns

output <- do.call(cbind, lapply(df1[-1], `*`, df2[-1]))
cbind(df1[1], setNames(output, paste0("r", seq_along(output))))

#  ID   r1   r2   r3   r4   r5   r6   r7   r8   r9
#1  1 0.06 1.20 1.80 0.02 0.40 0.60 0.04 0.80 1.20
#2  2 0.06 0.09 0.27 0.06 0.09 0.27 0.20 0.30 0.90
#3  3 0.10 0.22 0.14 0.05 0.11 0.07 0.35 0.77 0.49

You could use the dplyr package

#Example with dplyr

require(dplyr)
# First we use merge() to join both DF
result <- merge(df1, df2, by = "ID") %>% 
  mutate(r1 = x1*y1,
         r2 = x1*y2,
         r3 = etc.)

within mutate() you can specify your new column formulas and names

An option with map

library(tidyverse)
bind_cols(df1[1], map_dfc(df1[-1], `*`, df2[-1]))

Or in base R by replicating the columns and multiplying

out <- cbind(df1[1], df1[-1][rep(seq_along(df1[-1]), each = 3)] *
         df2[-1][rep(seq_along(df2[-1]), 3)])
names(out)[-1] <- paste0("r", seq_along(out[-1]))

out
#  ID   r1   r2   r3   r4   r5   r6   r7   r8   r9
#1  1 0.06 1.20 1.80 0.02 0.40 0.60 0.04 0.80 1.20
#2  2 0.06 0.09 0.27 0.06 0.09 0.27 0.20 0.30 0.90
#3  3 0.10 0.22 0.14 0.05 0.11 0.07 0.35 0.77 0.49

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM