【问题标题】:Why does this command work when hand-written, but not when the same inputs are drawn from a data.table为什么此命令在手写时有效,但在从 data.table 中提取相同输入时无效
【发布时间】:2020-07-03 07:34:57
【问题描述】:

总结:我有两行代码使用 data.table 和 rbind 从一个表中获取任意行列表,将它们添加到另一个表中,然后从原始表中删除这些行.我试图通过从第三个表的列中绘制这些输入(源表、目标表、行列表)来使其工作。 IE 而不是(伪代码示例)table1<-rbind(table1, table2[list_of_rownums_to_copy]) 我想让它像table3$col1<-rbind(table3$col1, table3$col2[table3$col4]) 一样干净地工作,其中 col1 和 col2 的每一行都包含其他表的名称,而 col4 包含行号列表。这样,我可以将命令包装在一个函数中,并使用mapply 或类似方法自动运行它多次。

详细说明: 出于测试目的,我创建了 dtA 到 dtF 表。它们都具有相同的格式,每个表的行数不同。这里的空间是唯一的表 dtA 的前 6 行。其他表是一样的,只是在“orig_table”列而不是“a”列中有字母:

     val     orig_table ##dtA has "a" in this column, dtB has "b", etc
1     1          a
2     2          a
3     3          a
4     4          a
5     5          a
6     6          a

只要我手写所有内容并给出一个列表对象,以下两行代码就可以在任意两个选定的表上完美运行:

dtA<- rbind(dtA, dtB[list_of_row_numbers, ])
dtB<- dtB[ -list_of_row_numbers, ]   

在这种情况下,dtA 是目标表,dtB 是源表,list_of_row_numbers 是一个列表对象,其中包含随机数,这些随机数作为要选择的行的行号。 IE 列表c(1, 3, 5) 会将表 dtB 中的第 1、3、5 行添加到表 dtA。第二行使用相同的列表来确定之后要从 dtB 中删除哪些行。与“剪切和粘贴”基本相同。

我所做的是创建另一个名为 dt1 的表,其中每一行是这两个命令的完整输入集。以下是head(dt1) 的输出供视觉参考:

    V1     V2    V3            V4
1: dtA    dtB   5804    3500,44228,22805,47866,32495,69006,...
2: dtA    dtC   5637    59773,55783,73482,84333,57466,88604,...
3: dtA    dtD   7292    67684,90789,67507,32937,90235,83391,...
4: dtA    dtE   3321    16810,12906,40822,40316,52624,85656,...
5: dtA    dtF   4268    89944,22578,23585,95320,79005,63923,...
6: dtB    dtA   3219    46716,54828,11475,29245,76940, 2535,...

第一行的内容对应于我给出的手写命令示例。第 V1 列的第 1 行是目标表 (dtA),第 1 行第 V2 列是源表 (dtB),第 1 列第 V4 列是要处理的行的列表:

 V1          V1   V2      V4
dtA<- rbind(dtA, dtB[list_of_row_numbers, ]) ## this copies rows from dtB to dtA
dtB<- dtB[ -list_of_row_numbers, ]   ## this deletes them from dtB afterwards

我试图让它直接接受来自表 dt1 的输入。最终目标是将这两行包装在一个函数中以与mapply 一起使用,以便遍历整个表 dt1,使用每行中列出的输入执行每个操作。

问题是我无法弄清楚执行此操作的语法。我尝试简单地将dt1$V1 替换为dtA,如下所示,但它根本不起作用:

dt1$V1<- rbind(dt1$V1, dt1$V2[dt1[,V4])
dt1$V2<- dt1$V2[ -dt1[,V4], ]

我之前通过将输入包装在 eval(as.name(dt1$V1)) 中解决了一个类似的问题,它有一个不同的命令来正确地将 row1 col1 解释为对象的名称而不仅仅是文本,但它在这里不起作用。

【问题讨论】:

  • 当然,我不确定你想要什么 dput。当我运行原始命令 dtA&lt;- rbind(dtA, dtB[list_of_row_numbers, ]) 时会发生什么?
  • 我想就是这样。用最简单的术语来说:表 dtA 到 dtF 是我关心的数据,以及所有实际操作都在其中发生的表。我想将表 dt1 的每一行用作“说明”。所以表 dt1 中的第 1 行表示“将列 V4 中列出的所有行从列 V2 中命名的表中取出,并将它们放入列 V1 中命名的表中”。在此dtB&lt;- dtB[ -list_of_row_numbers, ] 的末尾删除从原点移动的行。这就像 excel 中的“剪切和粘贴”。我在哪里可以找到更多关于为什么我的方法不起作用的信息?

标签: r function syntax data.table mapply


【解决方案1】:

我们可以通过 rbinding 包含“V2”列中的对象的数据集循环遍历行和 assign 每行中的对象

for(i in seq_len(nrow(dt1))) {

   assign(dt1$V1[i], rbind(get(dt1$V1[i]), get(dt1$V2[i])[dt1$V4[[i]],])) 
   assign(dt1$V2[i], get(dt1$V2[i])[-dt1$V4[[i]],])
 }

“V1”、“V2”列将对象名称存储为字符串。为了更新全局环境中的这些对象,我们需要将assign 对象设置为新值。例如

v1 <- 5
assign("v1", 10)
v1
#[1] 10

另外,由于对象名称是字符串,要从该字符串返回值,我们使用get

get("v1")
#[1] 10

在循环中,我们动态地使用assign 和get 在每次迭代中更新全局环境中的那些对象

【讨论】:

  • 据我所知,就是这样。如果不是太麻烦,您可以在这里解释或指出我在哪里可以找到解释为什么这有效但我的方法没有?我想了解您对get() 和assign() 的使用,以及为什么这与仅输入dt1$V1&lt;- rbind(dt1$V1, dt1$V2[dt1[,V4]) 的作用如此不同。我有一种感觉,这是因为我从根本上错过了关于 R 如何在引擎盖下工作的一些东西。
  • 我只是在测试它以验证它确实可以完全工作,我已经接受了。
  • @D3SL 我添加了一个简单的示例来理解这一点。希望对你有帮助
  • 确实如此,谢谢。我想我的方法的问题是 eval(as.name()) 在某些地方不起作用,所以需要使用 get/assign 。 for 循环遍历dt1 长度中的每个i(即行),并且由于i 在每个循环的持续时间内保持不变,它在功能上与我尝试使用的代码相同。每对操作都在相同的i(行)上执行。再次感谢您。
  • @D3SL 在这种情况下,assign 更直接。通常,我会将 data.frames 保存在 list 中并更新那些 list 元素,而不是全局环境中的多个对象
猜你喜欢
  • 1970-01-01
  • 2022-01-02
  • 2021-09-10
  • 1970-01-01
  • 1970-01-01
  • 2021-05-06
  • 2018-04-01
  • 1970-01-01
  • 2012-01-31
相关资源
最近更新 更多