【问题标题】:Multiplying two data sets and more in R在 R 中将两个数据集和更多数据相乘
【发布时间】:2016-12-23 15:52:18
【问题描述】:

我有两个具有公共列的数据框。

  # Generate DF1
    set.seed(219)
    x0 <- rnorm(5, 22, 17)
    x2 <- rnorm(5, 44, 15)
    x3 <- rnorm(5, 56, 13)
    x7 <- rnorm(5, 0, 3)
    x9 <- rnorm(5, 28, 31)
    x10 <- rnorm(5, 4, 75)
    x11 <- rnorm(5, 7, 1)
    dat1 <- data.frame(x0,x2,x3,x7,x9, x10, x11)
    dat1$ID1 <- rownames(dat1)

  # Generate DF2
    x1 <- rnorm(10, 2, 19)
    x2 <- rnorm(10, 4, 18)
    x3 <- rnorm(10, 5, 17)
    x4 <- rnorm(10, 7, 16)
    x5 <- rnorm(10, 8, 51)
    x6 <- rnorm(10, 9, 5)
    x7 <- rnorm(10, 0, 3)
    x8 <- rnorm(10, 34, 2)
    x9 <- rnorm(10, 28, 1)
    dat2 <- data.frame(x1,x2,x3,x4,x5,x6,x7,x8,x9)
    dat2$ID2 <- rownames(dat2)

请注意,DF1 有 5 行,而DF2 有 10 行。此外,每个数据框中的相似列名称并不意味着两列的值相同。

这是我想做的:

  1. 由于DF1 有5 行,我需要在DF2 中创建5 列,我们称它们为y1, y2, y3, y4, y5。

  2. 这是计算y1 的方法:我需要将DF1 中的第一行与DF2 中的所有行相乘。 y1 的大小将是(10 行和 1 列)。我需要为 DF2 中的每一行计算以下内容。

    y1 = x0 + x2(DF1)*x2(DF2) + x3(DF1)*x3(DF2) + x7(DF1)*x7(DF2) + x9(DF1)*x9(DF2)

同样,对于y2,我们需要从DF1的第二行开始...等

就向量和矩阵而言,这是计算 y1 的方法。

设 DF1 中的第一行为 (x01, x21, x31, x71, x91, x101, x111, ID11)。然后是 y1 的第一个值(记住 y1 是 10*1):

y11 = x01 + x21(DF1)*x21(DF2) + x31(DF1)*x31(DF2) + x71(DF1)*x71(DF2) + x91(DF1)*x91(DF2)。

y1的第二个值:

y12 = x01 + x21(DF1)*x22(DF2) + x31(DF1)*x32(DF2) + x71(DF1)*x72(DF2) + x91(DF1)*x92(DF2)。

...

最后,y1的第10个值是:

y110 = x01 + x21(DF1)*x210(DF2) + x31(DF1)*x310(DF2) + x71(DF1)*x710(DF2) + x91(DF1)*x910(DF2)。

如何实现我的算法?

【问题讨论】:

  • 那么,x0 是否会是常数 'y2'、'y3' 等。即,公式对于 'y2'、'y3' 等是否不同
  • 正确。因为 DF2 没有 x0.... 我可以将 DF2 中的 x0 添加为 1,然后执行 x0(DF1)*x0(DF2)。
  • 还有一个疑问,所以DF1中'x2'的第一行将乘以'DF2'中'x2'的所有行?
  • DF1 中的 x2 是一个数字,我需要为 DF2 中的每个 x2 乘以它。
  • 我也有同样的疑问/困惑。我认为这里的逻辑不太对劲。如果我们将 dat1 中的 1 个公共列的 1 行与 dat2 中该列的所有行相乘,那么长度将为 10x1。但是,您说的是 将 dat1 的唯一列添加到 all 4 个公共列的 10x1 乘积中,我不知道这如何适用于 10x1 向量.也许你可以给出一个逐步计算 y1 的例子。

标签: r


【解决方案1】:

这是基于我对您想要做什么的理解,我在评论中提到了这一点。

基本上,对于来自dat1 的非常见列,我将它们乘以一个向量以使它们成为一个一致的维度,然后为每个 y(y1 等)行添加 10x1 向量 -明智的做法是,每个都是一个 10x1 的向量:

common_cols <- intersect(colnames(dat1),colnames(dat2))
uniq_cols   <- setdiff(colnames(dat1),colnames(dat2))
uniq_cols   <- uniq_cols[!uniq_cols=="ID1"]

tmp  <- data.frame(y1=rep(NA,10), y2=rep(NA,10),y3=rep(NA,10),y4=rep(NA,10),y5=rep(NA,10))
tmp1 <- data.frame(matrix(nrow=10, ncol = 7))

for(i in 1:nrow(dat1)){
  for(j in 1:length(common_cols)){
    tmp1[,j] <-  dat1[i,common_cols[j]] * dat2[,common_cols[j]] 
  }
  for(k in 1:length(uniq_cols)){
    tmp1[,k+4] <- dat1[i,uniq_cols[k]]*rep(1,10)
  }
  tmp[,i] <- rowSums(tmp1)
}

结果是:

tmp
         y1          y2        y3        y4         y5
1  2796.812   226.31244 1924.2130 4392.7841  1459.8979
2  1786.241    17.11732  716.6079 2044.0003   141.6572
3  1371.890  -334.09190  324.3946 1578.0200  -262.0858
4  1235.717  -446.01583  176.2845 1422.1088  -411.2424
5  1995.976  -377.33202 1152.6527 3297.5986   635.7040
6  2233.255   197.51252 1155.2367 2847.4433   599.1098
7  3437.539  1675.03212 2328.7100 3876.5423  1914.7753
8   291.687 -1331.27575 -737.9568  299.7451 -1413.6779
9  1659.648  -244.14992  678.3120 2266.3193   144.3870
10 1675.775  -532.41657  668.3817 2491.0892    60.3962

【讨论】:

  • 我为上面的数据手动计算了 y11(相同的种子),但我得到了 2744.334(不是 2796.812)。我编辑了我的问题以显示 y1 的确切计算。谢谢。
  • @user9292 你能看一下逻辑,告诉我你的计算有什么不同吗?这应该是一个微不足道的改变,但现在我不确定逻辑在哪里不同。如果您在 R 中计算它,您可以将代码添加到您的问题中。
  • y11 4.3>
  • 我认为故障与您代码中的最后一段有关。 1) 我确实在 dat2 中添加了 x0 列作为 1。 2) tmp1 应该有 5 列而不是 7:tmp1
【解决方案2】:

使用dplyr 和tidyr 方法:

library(magrittr); library(dplyr)

生成 DF1

set.seed(219)
x0 <- rnorm(5, 22, 17)
x2 <- rnorm(5, 44, 15)
x3 <- rnorm(5, 56, 13)
x7 <- rnorm(5, 0, 3)
x9 <- rnorm(5, 28, 31)
x10 <- rnorm(5, 4, 75): i am commenting this out, based on your 
x11 <- rnorm(5, 7, 1): 
dat1 <- data.frame(x0,x2,x3,x7,x9, x10, x11)
# dat1$ID1 <- rownames(dat1) : not yet

生成 DF2

x1 <- rnorm(10, 2, 19)
x2 <- rnorm(10, 4, 18)
x3 <- rnorm(10, 5, 17)
x4 <- rnorm(10, 7, 16)
x5 <- rnorm(10, 8, 51)
x6 <- rnorm(10, 9, 5)
x7 <- rnorm(10, 0, 3)
x8 <- rnorm(10, 34, 2)
x9 <- rnorm(10, 28, 1)
dat2 <- data.frame(x1,x2,x3,x4,x5,x6,x7,x8,x9)
# dat2$ID2 <- rownames(dat2) : not yet

在 dat2 中创建缺失的变量

dat2$x0 <- 1
newCol <- names(dat1)[!(names(dat1) %in% names(dat2))]
dat2[, names(dat1)[!(names(dat1) %in% names(dat2))]] <- 0

行名列

dat1$ID1 <- rownames(dat1)
dat2$ID2 <- rownames(dat2)

表格从宽到长

df1 <- tidyr::gather(dat1, X, var, -c(ID1))
df2 <- tidyr::gather(dat2, X, var, -c(ID2))

连接两个表

df1 <- left_join(df1, df2, by="X")
rm(df2)

做你的乘法

df1$var <- df1$var.x * df1$var.y

创建 y 列

df1 %<>% group_by(ID1, ID2) %>% summarise(var=sum(var)) %>% ungroup %>% 
  mutate(ID1=paste0("y", ID1)) %>% 
  {left_join(dat2, tidyr::spread(., ID1, var), by="ID2")}

保留相关列

df1 <- df1[, names(df1)[!(names(df1) %in% newCol)]]

View(df1)

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2013-02-17
    • 1970-01-01
    • 2018-01-24
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多