【问题标题】:Function for Appending Rows to Data Frame Based on Previous Variable Values in R根据 R 中先前的变量值将行附加到数据帧的函数
【发布时间】:2016-06-29 13:55:45
【问题描述】:

我正在尝试创建一个函数,该函数允许我根据上一行(紧接在上面)中的变量多次将行附加到现有数据框中。

#Here's what I'm starting with 

Balance <- c(25000)
Pmt <- c(1500)
Interest <- c(.05)
DF <- data.frame(Balance,Pmt,Interest)
DF  
   Balance Pmt Interest
1   25000 100     0.05

例如,我想查看添加的下 4 行,其中新行的“余额”等于前一行的 ((Balance-Pmt)*(1+Inerest)),并且“ Pmt”和“Interest”行保持不变。

# Manually
DF[2,1] <- (DF[1,1] - DF[1,2])*(1+DF[1,3])
DF[2,2] <- DF[1,2]
DF[2,3] <- DF[1,3]
D
  Balance  Pmt Interest
1   25000 1500     0.05
2   24675 1500     0.05

很明显,我想复制多次,n,无需手动引用前一行。我想要一个函数,它允许我按照相同的逻辑向数据框添加行多次。任何帮助表示赞赏!

【问题讨论】:

    标签: r dataframe


    【解决方案1】:

    您可以设置数据框以考虑最终大小,而不是逐行构建数据框,这将是非常低效的。在此示例中,您知道您将运行此过程三次,以总共四行结束。首先制作该数据框,以使其余的更容易和更快:

    DF2 <- 'row.names<-'(DF[rep(1,4),], NULL)
    DF2$Balance <- Reduce(function(x,y) (x - y)*(1+DF2[1,3]), DF2[-1,2], init=DF[1,1], acc=TRUE)
    DF2
    #    Balance  Pmt Interest
    # 1 25000.00 1500     0.05
    # 2 24675.00 1500     0.05
    # 3 24333.75 1500     0.05
    # 4 23975.44 1500     0.05
    

    自学:Reduce 是如何工作的?

    Reduce 是一个更高级别的函数,它以一种需要练习才能掌握的独特方式工作。它包含两个主要部分,1) 具有两个参数的函数和 2) 单个向量*。这就是奇怪的部分。它需要一个具有两个 args 和 一个 向量的函数。起初这没有意义。它如何通过一个需要两个参数的函数的向量?示例:

    #one vector
    x <- c(2,3,4,5)
    
    #function with two arguments
    multiply <- function(a, b)  {a * b}
    

    这是一个从 2 到 5 的向量,以及一个简单的函数,它接受两个数字并将它们相乘。 Reduce 将接受这两个对象并执行以下操作:

    Reduce(multiply, x) #<- this
    #is the same as
    ans1 <- multiply(2, 3) 
    ans2 <- multiply(ans1, 4)
    ans3 <- multiply(ans2, 5)
    

    它通过向量c(2,3,4,5) 并获取前两部分(2 和 3)并在它们上调用函数。然后它接受该答案并引入 x (4) 的第三个元素来运行该函数,然后它接受该答案并与第四个元素 (5) 一起运行它。


    在您的示例中,我们使用它来处理第一笔余额和付款:

    #one vector
    x <- c(25000, 1500, 1500, 1500)
    
    #function with two arguments
    f <- function(a,b) (a - b)*(1 + 0.05)
    

    让我们看看它在内部做了什么:

    Reduce(f, x) #what we did
    #internally Reduce did this
    ans1 <- (25000 - 1500) * (1 + 0.05)
    ans2 <- (ans1 - 1500) * (1 + 0.05)
    ans3 <- (ans2 - 1500) * (1 + 0.05)
    

    这为我们提供了所需的过程。这就是我们所做的想法。为了完全完成我们的讨论,我们添加了两个额外的参数来帮助我们获得预期的结果。 accumulate=TRUEinit=DF[1,1]。第一个简单地告诉 Reduce 我们想要每个连续的答案,而不仅仅是最后一个。第二个告诉 Reduce 我们想要从什么值开始。展示 init 做了什么:

    #Supply vector for function
    x <- DF[-1,2]
    x
    [1] 1500 1500 1500
    
    #We need the initial balance
    #init=DF[1,1] does: 
    [1] 25000 1500 1500 1500
    

    Reduce 也可以采用列表,但我们应该先掌握向量,然后再引入列表方法。

    【讨论】:

      【解决方案2】:

      使用tvm: Time Value of Money Functions 包:

      library(tvm)
      
      n <- 5
      rem(cf = rep(1500, n), amt = 25000, r = 0.05)
      # [1] 24750.00 24487.50 24211.88 23922.47 23618.59
      

      【讨论】:

      • 结果不同。看起来 rem 正在使用不同类型的计算 amt * (1 + r)^t - sum(cf[1:t] * (1 + r)^(t - (1:t)))
      【解决方案3】:

      创建数据集:

          Balance <- c(25000)
          Pmt <- c(1500)
          Interest <- c(.05)
          DF <- data.frame(Balance,Pmt,Interest)
          DF
      1   25000 100     0.05
      

      然后使用函数说 n=10 次:

      > for(i in 2:10){
      +   DF[i,1] <- (DF[i-1,1] - DF[i-1,2])*(1+DF[i-1,3])
      +   DF[i,2] <- DF[i-1,2]
      +   DF[i,3] <- DF[i-1,3]
      + }
      > DF
          Balance  Pmt Interest
      # 1  25000.00 1500     0.05
      # 2  24675.00 1500     0.05
      # 3  24333.75 1500     0.05
      # 4  23975.44 1500     0.05
      # 5  23599.21 1500     0.05
      # 6  23204.17 1500     0.05
      # 7  22789.38 1500     0.05
      # 8  22353.85 1500     0.05
      # 9  21896.54 1500     0.05
      # 10 21416.37 1500     0.05
      

      您可以将 10 替换为 100 或 1000,具体取决于您要运行此函数的次数。

      【讨论】:

      • 这正是我想要的。感谢您的帮助!
      • 欢迎您!也许你可以接受这个作为答案:)
      【解决方案4】:

      你可以使用这个功能

      add_function <- function(n) invisible(replicate(n,{DF <<- rbind(DF,DF[nrow(DF),],make.row.names = F);DF[nrow(DF),1] <<- (DF[nrow(DF)-1,1]-DF[nrow(DF)-1,2])*(1+DF[nrow(DF)-1,3])}))
      

      只需提供n的值

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2020-03-13
        • 2019-05-15
        • 2016-01-31
        • 1970-01-01
        • 2020-05-25
        • 1970-01-01
        相关资源
        最近更新 更多