使用lapply使用基于列表的通用名称来rbind所有数据帧

时间:2017-12-21 21:14:40

标签: r lapply rbind

我有几个数据框如下:

orange_ABC
orange_BCD
apple_ABC
apple_BCD
grape_ABC
grape_BCD

我需要rbind那些具有共同名称的第一部分(橙色,苹果,葡萄)的人,并将新数据框命名为。我正在从数据框列表names(fruitlist)(我从中制作上述数据框)中访问这些名称,并尝试使用lapplyfunction(x)但没有运气。我对R来说有点新鲜,所以想想在动态命名新数据框时我犯了一个简单的错误...

lapply(names(fruitlist),
       function(x){
         frame_nm <- toString((names(fruitlist[x])))
         frame_nm <- do.call(rbind, mget(ls(pattern=paste0((names(splitlist[x])),"*"))))
})

我已经在一种水果&#34;上尝试了独立系列。它似乎有效:

test_DF <- do.call(rbind, mget(ls(pattern="apple*")))

编辑:我意识到我忘了提到6个数据框的示例列表是动态创建的,所以我不能简单地生成它们的列表。但是,我确实有一个&#34; fruits&#34;的列表,并且所有可能的新数据框名称的末尾都是已知的(&#34; _ABC&#34;和&#34; _BCD&#34;)

3 个答案:

答案 0 :(得分:1)

如果您的fruitlist是数据框的命名列表,则可能适用。

首先,将相同的名称放入他们自己的列表中:

fruit.groups <- split(names(fruitlist), 
                      sapply(strsplit(names(fruitlist), split = "_"), "[[", 1))

> fruit.groups
$apple
[1] "apple_ABC" "apple_BCD"

$grape
[1] "grape_ABC" "grape_BCD"

$orange
[1] "orange_ABC" "orange_BCD"

然后,按小组lapply使用rbind

fdf <- lapply(fruit.groups, function(x){
  out <- do.call(rbind, fruitlist[x])
  out$from <- gsub("(\\..*)", "", rownames(out))
  rownames(out) <- NULL
  return(out)
})

> fdf$apple
  a  b      from
1 1 11 apple_ABC
2 2 12 apple_ABC
3 3 13 apple_ABC
4 4 14 apple_ABC
5 1 11 apple_BCD
6 2 12 apple_BCD
7 3 13 apple_BCD
8 4 14 apple_BCD

虚假数据:

namelist <- paste(fruit = rep(c("orange", "apple", "grape"), 2), 
                  nums =  rep(c("_ABC", "_BCD"), each =  3), sep = "")

fruitlist <- llply(namelist, function(x){
  assign(as.character(x), data.frame(a = 1:4, b = 11:14))
})

修改

从编辑到您上面的问题:

如果您有水果和后缀,请使用expand.grid获取所有可能的组合(假设所有组合都将引用动态生成的数据框)。

fruits <- c("orange", "apple", "grape")
suffixes <- c("_ABC", "_BCD")
fullnames <- apply(expand.grid(fruits, suffixes), 1, paste, collapse = "")

使用该名称列表,使用mget生成当前数据框的列表。

new_fruit_df_list <- mget(fullnames)

然后,上面的代码应该工作,在这里修改以反映名称更改:

fruit.groups <- split(names(new_fruit_df_list),
                      sapply(strsplit(names(new_fruit_df_list), split = "_"), "[[", 1))

fdf <- lapply(fruit.groups, function(x){
  out <- do.call(rbind, new_fruit_df_list[x])
  out$from <- gsub("(\\..*)", "", rownames(out))
  rownames(out) <- NULL
  return(out)
})

看看每个人的头部,添加了一列(如果你不想要的话删除),显示该行的原始数据框的名称。

> lapply(fdf, head, 2)
$apple
  a  b      from
1 1 11 apple_ABC
2 2 12 apple_ABC

$grape
  a  b      from
1 1 11 grape_ABC
2 2 12 grape_ABC

$orange
  a  b       from
1 1 11 orange_ABC
2 2 12 orange_ABC

答案 1 :(得分:1)

如所怀疑的,建议的为对象赋值的方法不起作用。此外,在使用ls()mget()列出和访问函数中的命名对象时,必须小心,因为它们不会自动提升到父环境,只能在本地范围内“看到”变量,除非否则说。这适用于R版本3.4,旧版本可能表现不同。

  1. 创建命名对象。

    要在全球环境中创建新对象,请使用assign()(已在Luke C的回答中提出):

    > assign("foo", "some text")
    > foo
    [1] "some text"
    

    将代码放置在函数内部会导致局部范围。明确指定全局环境允许设置全局变量:

    > set_foo <- function (x) { assign("foo", x, envir=globalenv()) }
    > set_foo("other text")
    > foo
    [1] "other text"
    

    请注意,省略envir参数会使全局环境不受影响。

  2. 在本地函数中使用ls() / mget()

    默认情况下,这仅列出该函数的当前(本地)环境中的名称,该环境仅在问题中给出的示例代码中看到参数x。与上面类似,快速修复是通过添加参数envir=globalenv()来明确指定全局环境。这同样适用于mget()

  3. 由于没有提供MWE,我可以自由地调整Luke C答案中提供的“假数据”示例代码。

    # Populate environment
    namelist <- paste(fruit = rep(c("orange", "apple", "grape"), 2), 
                      nums =  rep(c("_ABC", "_BCD"), each =  3), sep = "")
    for(x in namelist)
      assign(x, data.frame(a = 1:4, b = 11:14))
    
    # The following re-generates the list of fruits used above
    grouplist <- unique(unlist(lapply(strsplit(namelist, "_"), function (x) { x[[1]] })))
    # Group and rbind by prefix, suppressing output
    invisible(lapply(grouplist,
           function(x) {
             grouped <- do.call(rbind,
               mget(ls(pattern=paste0(x,"_*"), envir=globalenv()),
                 envir=globalenv()))
             assign(x, grouped, envir=globalenv())
    }))
    

答案 2 :(得分:0)

尝试一下:

GeckoHtmlElement testelement = null;
            testelement = (GeckoHtmlElement)Browser.Document.GetHtmlElementById("class_test");
            string text = testelement.InnerHtml;