如何在 R 中创建一个数据框,当其他列之一发生更改时自动更新列?

How create a dataframe in R that updates columns automatically when one of the other columns has been changed?

这是我的输入

    > a<-data.frame(p=c(1:3),q=c(3:5))
    > a
      p q
    1 1 3
    2 2 4
    3 3 5
    > a<-a%>%mutate(r=p*q)
    > a
      p q  r
    1 1 3  3
    2 2 4  8
    3 3 5 15

修改其中一个单元格

   > a$p[1]<-2
   > a
     p q  r
   1 2 3  3
   2 2 4  8
   3 3 5 15     

a$r[1] 还没有更新到 2*3=6

我希望输出为:

    > a
      p q  r
    1 1 3  6
    2 2 4  8
    3 3 5 15

也就是说,我希望 r 的值在 p 或 q 之一发生变化时自动更新。

这可能不是您要查找的内容,但这是更新单个值并相应更新计算列的简单方法。我将使用 data.table 包,因为它允许您按行按引用更新列,因此您不必在每次更新时重新计算整个列。

首先,我向 a 添加一个属性,指定应更新的计算列。然后我定义了一个用于更新单个值的函数,该函数识别该属性并重新计算所定义的列。

a <- data.frame(p = c(1:3),q = c(3:5))
a <- a %>% mutate(r = p*q, s = p/q - 4)

library(data.table)
setDT(a)
attr(a, 'refresh.cols') <- c(r = 'p*q', s = 'p/q - 4')

df.update <- function(df, row, ...){
  l <- list(...)
  Map(function(x, nm) df[row, eval(parse(text = paste(nm, ':=', x)))]
      , l, names(l))
  df[row, names(attr(a, "refresh.cols")) := 
       lapply(attr(a, "refresh.cols"), function(x) eval(parse(text = x)))]
}
a
#    p q  r         s
# 1: 1 3  3 -3.666667
# 2: 2 4  8 -3.500000
# 3: 3 5 15 -3.400000

a %>% df.update(row = 1, p = 2)
a
#    p q  r         s
# 1: 2 3  6 -3.333333
# 2: 2 4  8 -3.500000
# 3: 3 5 15 -3.400000


a %>% df.update(row = 3, p = 6, q = 7)
a
#    p q  r         s
# 1: 2 3  6 -3.333333
# 2: 2 4  8 -3.500000
# 3: 6 7 42 -3.142857

a %>% df.update(row = 2, p = 9, q = 'p/3 + 1')
a
#    p q  r         s
# 1: 2 3  6 -3.333333
# 2: 9 4 36 -1.750000
# 3: 6 7 42 -3.142857

您正在尝试复制 Excel 用户体验,对吗?编辑一个单元格应更新所有相关单元格。

在 Excel 的背后——以及 R 中最终的解决方案——是对所有可能的逻辑下游值的重新计算。有些东西必须触发它。在Excel中,触发器正在更改单元格或执行重新计算命令。在 R 扩展中 Shiny 各种鼠标移动和点击都可以做到。

是的,您可以编写一个方法来查看 a$pa$q 的任何成员是否已更改,但也必须有某些东西触发该脚本。 R 并不提供一直 运行 的功能,就像您 PC 中等待键盘输入或鼠标移动的部分。在大多数情况下,R 进行所有可能的计算所花费的时间并不比仅根据 a[a,1].

的新值计算 a[1,3] 花费更长的时间

您可以创建一个函数来执行所有常规计算。您可以通过在控制台中键入 recalc() 来启动它。不需要任何参数。为它分配一个键盘快捷键,并在对数据对象进行任何更改后 运行 它。

    recalc <- function() {
      a$r <<- a$p * a$q
      ...
      ...
      TRUE
      }

超赋值运算符 <<- 允许您在全局环境中操作对象,就像您在控制台中键入命令一样。这通常不是构建函数的方式。