【问题标题】:different calculations for different subsets in r dataframer数据框中不同子集的不同计算
【发布时间】:2018-06-15 00:16:12
【问题描述】:

我正在尝试在我的 r 数据框中添加一列,根据直径计算干重(在多个日期测量多个生长物体的直径)。直径和干重之间的关系随着时间的推移而变化,这就是为什么我在不同的日期使用不同的公式。

object<-c(1,1,1,2,2,2)
date<-c(7,8,9,7,8,9)
diam<-c(2,3,4,1,3,5)
df<-data.frame(object,date,diam)

  object date diam
1      1    7    2
2      1    8    3
3      1    9    4
4      2    7    1
5      2    8    3
6      2    9    5

假设我想对日期 7 和 8 使用公式 y=5x+17,对日期 9 使用公式 y=3x+16。 我试过这个:

df$dw<-5*dw$diam-17[df$diam<=8]

但它告诉我替换和数据中有不同数量的行,这当然是正确的。如果我可以告诉它只将 NA 放在 df$diam>8 的位置,那就没问题了,但我不知道该怎么做。我曾尝试使用子集函数,但也没有任何运气。我唯一能想到的就是制作一大堆单独的数据框 - 每个公式一个,但这是一个不优雅(且复杂)的解决方案!

# desired outcome
df$dw
[1] 27 32 28 22 32 31

谢谢大家!

【问题讨论】:

  • 每个日期的测量次数是否相同?
  • 是的。我在每个日期测量了每个对象。
  • 最简单的方法(取决于你需要计算多少个日期以及你想对结果做什么)可能是为每个日期创建列,然后应用然后你可以应用相关公式到相关列。我会在一分钟内完成一些代码。

标签: r subset calculation


【解决方案1】:

使用 dplyr 的 case_when 的优雅、可读的解决方案将适用于无限数量的 date 子组。

library(dplyr)
df %>% 
  mutate( dw = case_when ( date %in% c(7,8) ~ diam * 5 + 17,
                           date %in% c(9)   ~ diam * 3 + 16 ) )

#   object date diam dw
# 1      1    7    2 27
# 2      1    8    3 32
# 3      1    9    4 28
# 4      2    7    1 22
# 5      2    8    3 32
# 6      2    9    5 31

【讨论】:

    【解决方案2】:

    一种方法(取决于您必须计算的日期以及您想要对结果执行的操作)可能是为每个日期创建列,然后应用,然后您可以将相关公式应用于相关列.

    library(tidyverse)
    df$date <- paste0("Day", df$date)
    df2 <- df %>% spread(date, diam)
    
    #  object Day7 Day8 Day9
    #1      1    2    3    4
    #2      2    1    3    5
    
    df2$Day7*5+17
    #[1] 27 22
    

    编辑:
    如果只有两个公式要计算(如上面的示例),则另一种、单行且更快的选项是:

    ifelse(df$date %in% c('Day7', 'Day8'), df$diam*5+17, df$diam*3+16)
    #[1] 27 32 28 22 32 31
    

    【讨论】:

    • 有超过 2 个日期,所以 ifelse 不起作用。我也害怕您的第一个建议,因为我将不可避免地难以将数据框恢复到适合我的某种顺序。因此,这似乎比将所有内容分成不同的数据框并稍后重新组合更难。我希望使用 which() 也许。我试过了,即使它在正确的行中输入了一个值,它也没有从同一行获取直径。上帝知道为什么(我当然不知道):D 谢谢!
    • 你的最终目标是什么?最后你想得到什么?
    • 我需要使用干重值来拟合曲线。
    • 你知道吗?我刚刚想通了。我有点像新手,所以我决定现在对自己很满意。我想这意味着我可以在这里回答我自己的问题,不是吗?!
    【解决方案3】:

    不确定这是否是最简单或最优雅的解决方案(可能不是),但这似乎可行:

    df$dw[which(df$date<=8)]<-5*df$diam[which(df$date<=8)]-17
    df$dw[which(df$date==9)]<-3*df$diam[which(df$date==9)]-16
    

    我玩了一段时间 which() 并不断收到错误消息,指出行数不同。我现在明白那是因为我在

    【讨论】:

    • 在你下面说ifelse 将不起作用,因为还有更多日期。你可以在ifelse 中使用&gt;&lt;
    • 也不需要调用whichdf$dw[df$date&lt;=8] &lt;- 5*df$diam[df$date&lt;=8]-17会做同样的事情。这称为“逻辑索引”,因为逻辑比较的 TRUE/FALSE 值允许您选择向量的元素或索引向量。
    • 哦,有道理,既然你提到了。谢谢!也许这是一个愚蠢的问题,但那有什么意义呢?
    猜你喜欢
    • 1970-01-01
    • 2020-11-23
    • 2021-05-06
    • 2013-09-27
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-09-24
    • 1970-01-01
    相关资源
    最近更新 更多