将所选列重新列表并合并到R中的数据框

时间:2016-09-12 16:13:04

标签: r

假设我有一个类似的列表:

int main (void)
{
    int min; /*variable to hold minutes*/
    printf ("How many minutes does it take you to use a shower? ");
    scanf ("%d", &min);
    while (min <= 0)
    {
        printf ("Please enter the positive number: ");
        scanf ("%d", &min);
    }
    int numbtl = min * 12; /*computes number of bottles*/
    printf ("Taking a shower you use %d bottles of water", numbtl);
    return 0;
}

我想要的是按列df1<-data.frame(n=letters[1:4], x=1:4, y=2:5, z=3:6) df2<-data.frame(n=letters[2:5], x=2:5, y=3:6, z=4:7) df3<-data.frame(n=letters[3:7], x=2:6, y=3:7, z=4:8) ls<-list(df1, df2, df3) ls [[1]] n x y z 1 a 1 2 3 2 b 2 3 4 3 c 3 4 5 4 d 4 5 6 [[2]] n x y z 1 b 2 3 4 2 c 3 4 5 3 d 4 5 6 4 e 5 6 7 [[3]] n x y z 1 c 2 3 4 2 d 3 4 5 3 e 4 5 6 4 f 5 6 7 5 g 6 7 8 合并列表中每个数据框的前两列,并且所需的输出将是:

n

y和z也一样:

  n x1 x2  x3
1 a   1  NA NA
2 b   2   2 NA
3 c   3   3  2
4 d   4   4  3
5 e  NA   5  4
6 f  NA  NA  5
7 g  NA  NA  6

2 个答案:

答案 0 :(得分:3)

我们从unique list获取data.frame列名称,但&#39; n&#39; (&#39; nm1&#39;),循环遍历那些(lapply(nm1,...),将每个数据框的列子集合在一起。在&#39; ls&#39; (lapply(ls, function(x) ...),并使用Reducemerge合并list中的数据集。

nm1 <- setdiff(unlist(lapply(ls, names)), "n")
lapply(nm1, function(nm)  setNames(Reduce(function(...)
    merge(..., all=TRUE, by = "n"), lapply(ls, 
                 function(x) x[c("n", nm)])), make.unique(c("n", rep(nm, length(nm1))))))
#[[1]]
#  n  x x.1 x.2
#1 a  1  NA  NA
#2 b  2   2  NA
#3 c  3   3   2
#4 d  4   4   3
#5 e NA   5   4
#6 f NA  NA   5
#7 g NA  NA   6

#[[2]]
#  n  y y.1 y.2
#1 a  2  NA  NA
#2 b  3   3  NA
#3 c  4   4   3
#4 d  5   5   4
#5 e NA   6   5
#6 f NA  NA   6
#7 g NA  NA   7

#[[3]]
#  n  z z.1 z.2
#1 a  3  NA  NA
#2 b  4   4  NA
#3 c  5   5   4
#4 d  6   6   5
#5 e NA   7   6
#6 f NA  NA   7
#7 g NA  NA   8

注意:ls是列出对象的函数名称。最好避免使用已知的R函数命名对象。

答案 1 :(得分:1)

以下是在嵌套的do.call函数对中使用data.framecbindlapply的另一种基本R方法。

# get all levels of n across data frames
allN <- unique(unlist(sapply(ls, "[[", "n")))
# extract desired columns and provide names with setNames
lapply(names(ls[[1]])[-1], function(var) {
       cbind("n"=allN, setNames(do.call(data.frame,
         lapply(seq_along(ls), function(i) {
                                 ls[[i]][[var]][match(allN, ls[[i]]$n, nomatch=NA)]
                               })), paste0(var, seq_along(ls))))
})

第一个lapply遍历每个变量名,第二个lapply从列表中的每个数据框中提取当前变量。在中间,do.call使列表成为data.frame,setNames提供所需的名称,n列添加cbind

在内部lapply的最里面部分,代码ls[[i]][[var]][match(allN, ls[[i]]$n, nomatch=NA)]用于根据allN中的级别扩展(并可能重新排序)当前向量。如果当前向量缺少某个级别,则nomatch = NA会让match返回NA