【问题标题】:Normalize a vector based on two other values根据其他两个值对向量进行归一化
【发布时间】:2012-11-19 10:41:15
【问题描述】:

我有以下数据框

df <- data.frame(
  Type=rep(LETTERS[1:6],3),
  Level=rep(1:3,each=6),
  Value=1:18)

我想添加 2 列,

  • 添加 'r1',Value 与同一级别的 Type A 值的比率
  • 添加 'r2',Value 与同一类型的 Level 1 值的比率

结束

> df
   Type Level Value       r1   r2
1     A     1     1 1.000000  1.0
2     B     1     2 2.000000  1.0
3     C     1     3 3.000000  1.0
4     D     1     4 4.000000  1.0
5     E     1     5 5.000000  1.0
6     F     1     6 6.000000  1.0
7     A     2     7 1.000000  7.0
8     B     2     8 1.142857  4.0
9     C     2     9 1.285714  3.0
10    D     2    10 1.428571  2.5
11    E     2    11 1.571429  2.2
12    F     2    12 1.714286  2.0
13    A     3    13 1.000000 13.0
14    B     3    14 1.076923  7.0
15    C     3    15 1.153846  5.0
16    D     3    16 1.230769  4.0
17    E     3    17 1.307692  3.4
18    F     3    18 1.384615  3.0

我尝试了一些apply 类型的方法,但无法得到它。我最终得到了一个双 for 循环:

for(i in unique(df$Type)) {
  for(j in unique(df$Level)) {
    df$r1[df$Level==j & df$Type==i] <- df$Value[df$Level==j & df$Type==i]/df$Value[df$Level==j & df$Type=="A"]
    df$r2[df$Level==j & df$Type==i] <- df$Value[df$Level==j & df$Type==i]/df$Value[df$Level==1 & df$Type==i]
  }
}

这还不错,但我想知道是否有一种拆分-应用-组合的方法可以做到这一点,也许在plyr 中有一些东西。

【问题讨论】:

    标签: r plyr


    【解决方案1】:

    既然您提出了plyr 解决方案:

    df <- ddply(df, .(Level), transform, r1 = Value / Value[Type == "A"])
    df <- ddply(df, .(Type),  transform, r2 = Value / Value[Level == 1])
    

    我觉得很好读。

    【讨论】:

    • 除非 ddply 正在做我不理解的事情(这很有可能),否则看起来您正在执行向量操作 df$Value/df$Value[df$Type=="一个”]。这会以错误的顺序回收三个“A”值的元素。因此在我的回答中调用了 rep()。
    • 不,它正在做正确的事情。 ddply 的第二个参数是用于对数据进行分组的变量,因此有例如每个Level 一个Type == "A" 而不是你建议的三个。您可以只运行我的解决方案来检查它是否正确并与您的结果相匹配。它也更通用,因为它不依赖于您做出的组必须具有相同长度的假设。
    • 确实如此。我需要学习 plyr。有趣的是它重新排序了数据框的行。
    • 是的,这正是我正在寻找的东西。我没有考虑过使用transform 来实现该功能。谢谢。
    • @MatthewLundberg 并且有趣的是,如果这两个语句以相反的顺序运行,则数据框将按原始顺序保留。我猜每个语句中的重组与它的拆分方式是一致的。
    【解决方案2】:

    先创建向量,然后将它们绑定到数据框:

     r1 <- df$Value / df$Value[rep(df$Value[df$Type=='A'], each=length(levels(df$Type)))]
     r2 <- df$Value / df$Value[seq_along(levels(df$Type))]
    

    这假设每个“级别”都重复“类型”,如您的示例所示。

    这是适当的 cbind() 调用:

    cbind(df, r1, r2)
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2011-10-09
      • 2016-03-09
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2010-12-06
      • 1970-01-01
      相关资源
      最近更新 更多