【问题标题】:How to calculate weighted sums of rows based on value in another column如何根据另一列中的值计算行的加权总和
【发布时间】:2017-05-08 11:22:48
【问题描述】:

我搜索了很多试图找到答案。这似乎是一个相对简单和常见的问题,我很惊讶我没有找到答案,但也许我只是没有搜索正确的关键字。

我想根据另一列中的值计算三行中某些列的加权和。如果您查看下面的虚拟表,我认为它更有意义。

INDIVIDUAL <- c("A","A","A","A","A","A","B","B","B","B","B","B")

BEHAVIOR <- c("Smell", "Dig", "Eat", "Smell", "Dig", "Eat","Smell", "Dig", "Eat","Smell", "Dig", "Eat")

FOOD <- c("a", "a", "a","b","b","b", "a", "a", "a","b","b","b")

TIME <- c(2,4,7,6,1,2,9,0,4,3,7,6)

sample <- data.frame(Individual=INDIVIDUAL, Behavior=BEHAVIOR, Food=FOOD, Time=TIME)

每个人都会花费一定的时间来闻、挖掘和吃每种食物。我想对这三个时间进行加权和求和,以使每个食品有一个总时间。闻是最轻的,吃是最重的。所以基本上我想要与每种食物互动的时间:每个FoodA的时间=(EatA)+(0.5*DigA)+(0.33*SmellA)。

在广泛浏览网页后,我能想到的最佳想法是:

sample %>%
  group_by(Individual, Food) %>%
  mutate(TIME = ((fullsum$BEHAVIOR == "EAT")
        +(.5*(fullsum$BEHAVIOR == "DIG")
        +(.33*(fullsum$BEHAVIOR == "SMELL")))))

但它不起作用,我收到此错误:mutate_impl(.data, dots) 中的错误:大小不兼容 (2195),期望为 1(组大小)或 1。

任何已回答此问题的建议或指导将不胜感激!

最终结果

我修改了 fexjoo 的建议以考虑缺失值,结果与我在 Excel 中手动计算的值相匹配,所以看起来这是赢家。可能有一种更简洁的方法可以从每一列中删除 NA,但我可以接受。

data.frame %>%
  spread(BEHAVIOR, TIME) %>%
  mutate(EAT = coalesce(EAT, 0)) %>%
  mutate(DIG = coalesce(DIG, 0)) %>%
  mutate(SMELL = coalesce(SMELL, 0)) %>%
  mutate(TIME = EAT + .5*DIG + .33*SMELL)

【问题讨论】:

  • 我不完全清楚你是如何计算权重的。他们是任意的吗?

标签: r dplyr


【解决方案1】:

试试这个

sample %>% 
group_by(Individual, Food) %>%
mutate(TIME = ((Behavior == "Eat") + (.5*(Behavior == "Dig")
                       +(.33*(Behavior == "Smell")))))

【讨论】:

  • 我应该提到,我之前确实尝试过,但我认为它根本不起作用,因为前几十个 TIME 值是 0。但我只是按照你的建议再次做了并滚动再往下,所有时间值都是 0 或 0.33,或 0.5,或 1.0。
【解决方案2】:

我的建议:

library(tidyr)

sample %>%
  spread(Behavior, Time) %>%
  mutate(TIME = Eat + .5*Dig + .33*Smell)

结果是:

  Individual Food Dig Eat Smell  TIME
1          A    a   4   7     2  9.66
2          A    b   1   2     6  4.48
3          B    a   0   4     9  6.97
4          B    b   7   6     3 10.49

【讨论】:

  • spread 来自tidyr 包(也在tidyverse 中)仅供参考
  • 感谢您的完成@Dan!我大部分时间都在使用tidyverse。有时让我忘记不同的包裹:)
  • 这行得通,但由于我有一些缺失值(即不是每个人都吃、闻、挖每件物品),我不得不在我的管道中用 0 替换 NA。感谢您的输入!
  • @KatieSmith 我的回答是否解决了您的问题(除了您在帖子中未提及的 NA 值这一事实),我说得对吗?如果您将我的答案标记为解决方案,那就太好了! :)
【解决方案3】:

你可以这样做:

sample %>% 
mutate(weights=case_when(.$Behavior=="Smell"~0.33,.$Behavior=="Dig"~0.5,.$Behavior=="Eat"~1)) 
    %>% group_by(Food,Individual) 
    %>% summarise(WeightedTime=sum(weights*Time))

这给出了:

     Food Individual WeightedTime
  <fctr>     <fctr>        <dbl>
1      a          A         9.66
2      a          B         6.97
3      b          A         4.48
4      b          B        10.49

【讨论】:

  • 当我运行此程序时,我收到错误:resolve_vars(new_groups, tbl_vars(.data)) 中的错误:要分组的未知变量:个人。可能是我的数据集的问题,但由于其他选项之一有效,我不打算对其进行故障排除。不过感谢您的建议!
【解决方案4】:

您可以根据Behavior 列创建具有权重的列:

library(dplyr)    
sample$weights <- 
    case_when(
        sample$Behavior == "Smell" ~ 0.33,
        sample$Behavior == "Dig" ~ 0.5,
        sample$Behavior == "Eat" ~ 1
    )

sample %>% group_by(Individual, Food) %>% 
    summarise(time = sum(Time * weights))

【讨论】:

  • 当我运行这个时,我在第一部分遇到了一个错误:$&lt;-.data.frame(*tmp*, "WEIGHTS", value = c(0.33, 0.5, 1, : 替换有 12 行,数据有 2194。可能是我的数据集有问题,但由于其他选项之一有效,我不打算对其进行故障排除。感谢您的建议!
猜你喜欢
  • 2017-08-20
  • 1970-01-01
  • 2021-09-12
  • 1970-01-01
  • 1970-01-01
  • 2020-09-26
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多