如何在 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$p
或 a$q
的任何成员是否已更改,但也必须有某些东西触发该脚本。 R 并不提供一直 运行 的功能,就像您 PC 中等待键盘输入或鼠标移动的部分。在大多数情况下,R 进行所有可能的计算所花费的时间并不比仅根据 a[a,1]
.
的新值计算 a[1,3]
花费更长的时间
您可以创建一个函数来执行所有常规计算。您可以通过在控制台中键入 recalc()
来启动它。不需要任何参数。为它分配一个键盘快捷键,并在对数据对象进行任何更改后 运行 它。
recalc <- function() {
a$r <<- a$p * a$q
...
...
TRUE
}
超赋值运算符 <<-
允许您在全局环境中操作对象,就像您在控制台中键入命令一样。这通常不是构建函数的方式。
这是我的输入
> 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$p
或 a$q
的任何成员是否已更改,但也必须有某些东西触发该脚本。 R 并不提供一直 运行 的功能,就像您 PC 中等待键盘输入或鼠标移动的部分。在大多数情况下,R 进行所有可能的计算所花费的时间并不比仅根据 a[a,1]
.
a[1,3]
花费更长的时间
您可以创建一个函数来执行所有常规计算。您可以通过在控制台中键入 recalc()
来启动它。不需要任何参数。为它分配一个键盘快捷键,并在对数据对象进行任何更改后 运行 它。
recalc <- function() {
a$r <<- a$p * a$q
...
...
TRUE
}
超赋值运算符 <<-
允许您在全局环境中操作对象,就像您在控制台中键入命令一样。这通常不是构建函数的方式。