循环中保持变量名称R

4
我想创建一个循环,遍历3个数据框并创建它们的子集,并将这些新子集分配一个新名称。如何在保持名称的情况下循环遍历这三个数据框?
例如,我有3个数据框:apples,berries和grapes。在制作循环时,是否有一种方法可以为其各自原始数据框类似的名称分配新的子集数据框?
不使用循环写出来的代码如下所示。
apples <- data.frame(type = c("red", "golden", "green"), number = c(1, 2, 3))
berries <- data.frame(type = c("blueberry", "raspberry", "mulberry"), number = c(1, 2, 3))
grapes <- data.frame(type = c("red", "green", "sour"), number = c(1, 2, 3))

apples_large <- subset(apples, number > 2)
apples_small <- subset(apples, number < 2)

berries_large <- subset(berries, number > 2)
berries_small <- subset(berries, number < 2)

grapes_large <- subset(grapes, number > 2)
grapes_small <- subset(grapes, number < 2) 

2
最好不要在全局环境中创建多个对象。 - akrun
你是如何创建这些数据框的?如果这些值是相关的,并且您想对它们执行类似的操作,那么它们应该都在同一个列表中。这样更容易处理。请参见:https://dev59.com/22Mm5IYBdhLWcg3wlvwK 和此相关答案:https://stackoverflow.com/a/51560385/2372064 - MrFlick
或许有帮助:https://dev59.com/22Mm5IYBdhLWcg3wlvwK - r2evans
看一下assign函数。 - JonMinton
3个回答

4

将数据集对象放入一个list中,并按照“number”列进行split,以获得嵌套的数据集list

lapply(list(apples, berries, grapes), function(x) split(x, x$number>2)) 

如果我们创建一个命名的“list”,那么识别或提取单个组件就会变得更加容易。
out <- lapply(mget(c("apples", "berries", "grapes")),
  function(x) split(x, c("small", "large")[(x$number > 2) + 1]))
out$apples$small

正如@JonMinton所提到的那样,如果我们需要删除具有“数字”2的行

lapply(mget(c("apples", "berries", "grapes")),
       function(x) {x1 <- subset(x, number != 2)
             split(x1, c("small", "large")[(x1$number > 2) + 1])})   

1
Split 只在分割是互斥且穷尽的情况下起作用。在这个例子中,子集是 <2 和 >2,所以 ==2 被删除了。 - JonMinton

3

在全局环境中创建许多对象而不是将它们保存在列表中是一个不好的想法,但是可以这样做:

tmp <- c("apples", "berries", "grapes")

for (i in 1:length(tmp)){
  assign(paste0("big_", tmp[i]), subset(get(tmp[i]), number > 2))
  assign(paste0("small_", tmp[i]), subset(get(tmp[i]), number < 2))
}

(或者使用seq_along(tmp)代替1:length(tmp)

注意使用assign来输出结果,get来输入内容。


1
尽管这些事情做起来不好,但了解如何做它们是很有用的。 - flies

1

首先,将你的 data.frames 放入一个 list 中,然后定义一个分类行的函数。现在,你可以使用 lapply 按照你的分类器来拆分列表中的每个元素。

fruits <- list(
    apples=data.frame(type = c("red", "golden", "green"), number = c(1, 2, 3)),
    berries=data.frame(type = c("blueberry", "raspberry", "mulberry"), number = c(1, 2, 3)),
    grapes=data.frame(type = c("red", "green", "sour"), number = c(1, 2, 3))
)

clsfy <- function(num) {
    if (num>2) {
        ret <- "Large"
    } else if (num<2) {
        ret <- "Small"
    } else {
        ret <- NA ## if no condition is met, discard this row
    }
    return(ret)
}

fruits2 <- lapply(fruits, function(fr) {
    split(fr, sapply(fr$number, clsfy))
})

此时,fruits2看起来是这样的:
>     fruits2
$apples
$apples$Large
   type number
3 green      3

$apples$Small
  type number
1  red      1


$berries
$berries$Large
      type number
3 mulberry      3

$berries$Small
       type number
1 blueberry      1


$grapes
$grapes$Large
  type number
3 sour      3

$grapes$Small
  type number
1  red      1

为了使用一行中的多列进行分类,您可以使用apply而不是sapply并重新定义您的clsfy函数,使其接受整行:split(fr, apply(fr, 1, clsfy))。另一方面,如果您的条件真的是一个简单的二进制条件,则ifelsesapply(x$number, clsfy)更好。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接