我如何模仿新行的拖动功能,例如在 Excel 中,但在 R 中?

Posted

技术标签:

【中文标题】我如何模仿新行的拖动功能,例如在 Excel 中,但在 R 中?【英文标题】:How do I mimic the drag functionality for new rows such as in Excel but for R? 【发布时间】:2021-11-30 09:22:14 【问题描述】:

lead()lag() 对每个填充的行没有动态/按顺序拖动,这让我有些不安。

我的愿望是根据初始值填充新行,然后根据先前填充的行顺序填充下一行。在 Excel 中,这可以通过在单元格中说明公式/函数并拖动它来完成。我如何在 R 中做到这一点?

见下例

       x     y     z
   <dbl> <dbl> <dbl>
 1     1     1     1
 2     2     3    NA
 3     3     5    NA
 4     4     7    NA
 5     5     9    NA
 6     6    11    NA
 7     7    13    NA
 8     8    15    NA
 9     9    17    NA
10    10    19    NA 

所需的输出遵循此计算,其中t-1 是先前值的下标: Z = Z_t-1 + X_t-1 - Y_t-1.

期望的输出

       x     y     z
   <dbl> <dbl> <dbl>
 1     1     1     1
 2     2     3     1
 3     3     5     0
 4     4     7    -2
 5     5     9    -6
 6     6    11    -12
 7     7    13    -18
 8     8    15    -25
 9     9    17    -33
10    10    19    -42 

【问题讨论】:

您想要的输出与您声明的公式不匹配。例如,在第 5 行中,前一行 x 的值为 4,前一行 z 的值为 -2。这些总和为 2,因此当您减去 7(前一行中 y 的值)时,您应该得到 -5,而不是 -6。 【参考方案1】:

请注意,您的问题中所需的结果与您描述的公式的输出不匹配。

在这种特定情况下,您可以使用cumsum(累计)得到答案:

cumsum(df1$x - df1$y + 1)
 [1]   1   1   0  -2  -5  -9 -14 -20 -27 -35

然而,一般来说,如果你想根据前一个结果的输出递归地应用一个函数,你需要写一个循环来完成它(或者使用一个使用循环的函数“在引擎盖下”,正如 akrun 用accumulate 展示的那样)。实现您的结果的基本 R 中的一个简单循环是:

for(i in 2:nrow(df1)) df1$z[i] <- df1$z[i-1] + df1$x[i-1] - df1$y[i-1] 

df
#>     x  y   z
#> 1   1  1   1
#> 2   2  3   1
#> 3   3  5   0
#> 4   4  7  -2
#> 5   5  9  -5
#> 6   6 11  -9
#> 7   7 13 -14
#> 8   8 15 -20
#> 9   9 17 -27
#> 10 10 19 -35

当您可以使用像 cumsum 这样使用基于 C 的矢量化而不是 R 中的循环的函数时,它可能是更有效的解决方案。

【讨论】:

谢谢,你的 forloop 甚至可以解决更大的数据集,但它的计算效率很低。通过修改代码,使用累积不会推广到其他数据集。你知道为什么吗?例如。 ~1.2mill 行,包含 16 个变量和分组数据。【参考方案2】:

与 cmets 一样,预期输出与指定的公式不匹配。在tidyverse中,递归操作可以用accumulate完成

library(purrr)
library(dplyr)
df1 %>% 
   mutate(z = unlist(accumulate2(x, y, ~ ..1 + ..2 - ..3, 
       .init = first(z))[-(n()+1)]))

-输出

   x  y   z
1   1  1   1
2   2  3   1
3   3  5   0
4   4  7  -2
5   5  9  -5
6   6 11  -9
7   7 13 -14
8   8 15 -20
9   9 17 -27
10 10 19 -35

数据

df1 <- structure(list(x = 1:10, y = c(1L, 3L, 5L, 7L, 9L, 11L, 13L, 
15L, 17L, 19L), z = c(1L, NA, NA, NA, NA, NA, NA, NA, NA, NA)), 
class = "data.frame", row.names = c("1", 
"2", "3", "4", "5", "6", "7", "8", "9", "10"))

【讨论】:

谢谢,我可以在特定数据集上复制您的代码。但是为什么我不能通过修改将它推广到其他数据集上呢? @geometricfreedom 取决于您使用的功能,还请检查列是否属于numeric/integer @geometricfreedom 你说的代码修改。我猜您的修改可能会产生影响,即在不知道您更改了什么的情况下,不确定 假设数据中有组和更多列,这将创建此代码(除了组列是整数之外的所有数字): df %>% group_by(group_col) %>% mutate(z = unlist (accumulate2(x,y,v,u, ~ ..1 + ..2 - ..3 - ..4 - ..5, .init = first(z))[-n()+1)]) ) @geometricfreedom accumulate2 只能占用 2 列且不超过 2

以上是关于我如何模仿新行的拖动功能,例如在 Excel 中,但在 R 中?的主要内容,如果未能解决你的问题,请参考以下文章

Excel VBA:编辑新行的现有条件格式规则

如何在 ios 模拟器上模仿两指滚动/拖动手势?

如何禁用在handsontable中添加新行/列?

如何使用 PHPSpreadsheet 在 Excel 上添加新行

如何在 MS Excel 中将单元格值与新行连接起来?

excel - 自动填充递增多个数字