在R中,如果符合另一个数据框中的条件,则对数据框中行中的数据点求和。

3
我有两个数据框,每个数据框都有220个观测值和80个变量。第一个数据框df1只包含数据点1、2和3。第二个数据框df2包含不同的数字值,包括小数,如0.12、-0.03、0.01等(用于表示给定月份的市值加权股票回报)。注:原始数据集的长度为80。
例如:
df1 = data.frame(a = c(2, 2, 1), b = c(3, 2, 3), c = c(1, 1, 2), d = c(3, 3, 1))

  a b c d
1 2 3 1 3
2 2 2 1 3
3 1 3 2 1

df2 = data.frame(a = c(0.1, 0.1, 0.2), b = c(0.3, 0.4, 0.6), c = c(0.2, 0.3, 0.5), d = c(0.1, 0.5, 0.6))

    a   b   c   d
1 0.1 0.3 0.2 0.1
2 0.1 0.4 0.3 0.5
3 0.2 0.6 0.5 0.6

如何根据df1中的值对df2的行进行求和,并将其转换为一个矩阵,其中有220个观测值和3个变量。请注意,df1和df2具有相同的列名且顺序相同。如何基于df1的指示变量创建第三个数据框df3,通过对df2的行进行求和?我想根据df1中的值对df2的行进行求和,以创建df3。
df3 =
   X1  X2  X3
1 0.2 0.1 0.4
2 0.3 0.5 0.5
3 0.8 0.5 0.6

让我们首先看一下 (X1,1)。在 df1 中,第一行只包含一个数据点,其值为 1,即 (c,1)。因此,我们将 df2 的第一行相加,得到 0.2。现在看一下 (X1,3)(列 X1 的最后一个值)。观察 df1 中的第三行,找到两个值为 1 的数据点。在 df2 中,这两个值分别是 0.2 (a,3)0.6 (d,3),将它们相加得到 0.8
以下是关于 df3 的说明:
calculation = data.frame("1" = c("0+0+0.2+0", "0+0+0.3+0", "0.2+0+0+0.6"), "2" = c("0.1+0+0+0", "0.1+0.4+0+0", "0+0+0.5+0"), "3" = c("0+0.3+0+0.1", "0+0+0+0.5", "0+0.6+0+0"))

                 X1                X2                X3
1   0 + 0 + 0.2 + 0   0.1 + 0 + 0 + 0 0 + 0.3 + 0 + 0.1
2   0 + 0 + 0.3 + 0 0.1 + 0.4 + 0 + 0   0 + 0 + 0 + 0.5
3 0.2 + 0 + 0 + 0.6   0 + 0 + 0.5 + 0   0 + 0.6 + 0 + 0

基于股票的更实用的解释。假设df1是描述买入、持有和卖出建议的矩阵。df2描述了市场加权股票回报率。所有的变量/列都是不同的股票。df3创建了一个包含三个不同组合的矩阵。如果股票是“买入”,我想把它放在“买入”组合中。如果股票是“持有”,我想把它放在“持有”组合中,等等。这在Excel中可以使用嵌套的IFANDOR函数轻松完成,但我不知道如何在R中完成。
2个回答

3
我们可以使用tapply函数,将数据集转换为矩阵(matrix),并将分组变量作为数据的行(row)索引和'df1'的索引。
tapply(as.matrix(df2), list(row(df2), as.matrix(df1)), FUN = sum)
#       1   2   3
#[1,] 0.2 0.1 0.4
#[2,] 0.3 0.5 0.5
#[3,] 0.8 0.5 0.6

或者使用 tidyverse,在将这两个数据集转换为“长”格式后,绑定数据集,然后按组进行 sum

library(tidyverse)
gather(df1) %>%
    bind_cols(gather(df2)) %>% 
    group_by(key) %>%
    group_by(rn = row_number(), value) %>% 
    summarise(value1 = sum(value1)) %>% 
    spread(value, value1) %>% 
    ungroup %>% 
    select(-rn)
# A tibble: 3 x 3
#    `1`   `2`   `3`
#  <dbl> <dbl> <dbl>
#1   0.2   0.1   0.4
#2   0.3   0.5   0.5
#3   0.8   0.5   0.6

@Mataunited17 是的,唯一的原因是原始数据中长度不相等,而在示例中长度相同。 - akrun
我明白了。df1df2的原始数据长度都为80。 - Mataunited18
@Mataunited17 我的意思是对于每一行,统计'df1'元素的频率。 - akrun
是的。原始数据中行元素的频率将不同。然而,在示例数据中,每行的频率为1或2。 - Mataunited18
1
我懂了。我必须删除所有的0和4,这样才能将其分成3个数组而不是5个。感谢您的帮助! - Mataunited18
显示剩余3条评论

2

这里是另一种使用rowsum进行分组求和并通过mapply循环行的基本R方法。

t(mapply(rowsum, as.data.frame(t(df2)), as.data.frame(t(df1))))
   [,1] [,2] [,3]
V1  0.2  0.1  0.4
V2  0.3  0.5  0.5
V3  0.8  0.5  0.6

请注意,我使用的是R 3.4.4版本。我认为,在R 3.5.0+版本中不需要使用as.data.frame函数,因为当将数据框作为参数传入t函数时,t函数应该会返回一个数据框。

2
很好的选择。我也在考虑rowsum - akrun
2
这需要进行多次转置,但对于中等大小的数据来说不应该太麻烦。 - lmo
@lmo 这在我的原始数据集中没有效果。它仅为每个数据点给出多个字符向量的行向量。 - Mataunited18
我的猜测是你的一些变量是字符类型。转置会将数据框转换为字符矩阵。我会怀疑 rowsum 会在此出错,但如果没有看到你的原始数据,很难诊断。 - lmo

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接