R使用lapply()填充并命名数据帧列表中的一列

时间:2019-05-06 19:56:23

标签: r list dataframe lapply names

搜索一段时间后,找不到平滑的R形解决方案。

我有一个向量列表,我想将其转换为数据帧并添加带有向量名称的列。我不能使用cbind()和melt()到单个数据框b / c来做到这一点,其中存在具有不同行数的向量。

基本示例为:

list<-list(a=c(1,2,3),b=c(4,5,6,7))
var<-"group"

我想出并起作用的是:

list<-lapply(list, function(x) data.frame(num=x,grp=""))

for (j in 1:length(list)){
  list[[j]][,2]<-names(list[j])
  names(list[[j]])[2]<-var
}

但是我试图更好地使用lapply()并拥有更简洁的编码实践。现在,我非常依赖for和if语句,许多基本函数已经执行了它们,并且比现在的代码效率更高。

我想要的伪代码类似:

list<-lapply(list, function(x) data.frame(num=x,get(var)=names(x))

有没有一种干净的方法可以做到这一点?

第二个密切相关的问题,如果我已经有了一个数据框列表,为什么使用lapply()重新分配列值和名称如此困难?

所以使用类似的东西:

list<-list(a=data.frame(num=c(1,2,3),grp=""),b=data.frame(num=c(4,5,6,7),grp=""))
var<-"group"

#pseudo code
list<-lapply(list, function(x) x[,2]<-names(x)) #populate second col with name of df[x]
list<-lapply(list, function(x) names[[x]][2]<-var) #set 2nd col name to 'var'

伪代码的第一行引发有关匹配行长度的错误。为什么lapply()不仅会循环并像在单个数据帧上的相同函数一样重复name(x)会在for循环中发生?

对于第二行,据我了解,我可以使用setNames()重新分配所有列名,但是如何仅对其中一个列名进行这项工作呢?

非常感谢您提出的任何想法或指向涵盖此主题并帮助我理解lapply()在这种情况下的行为的其他线索。

3 个答案:

答案 0 :(得分:3)

不使用循环的完整R基础方法

List<IFruitPayment> fruitPayments = new ArrayList<>():
        fruitPayments.add(new FruitUnit());
        fruitPayments.add(new FruitVolume());
        fruitPayments.add(new FruitWeight());
        for(IFruitPayment payment:fruitPayments) {
            System.out.println(payment.payFruit());
        }

答案 1 :(得分:1)

关于第一个/主要问题,您可以为此使用软件包enframe中的函数tibble

library(tibble)
library(tidyr)
library(dplyr)

l<-list(a=c(1,2,3),b=c(4,5,6,7))

l %>% 
  enframe(name = "group", value="value") %>% 
  unnest(value) %>% 
  group_split(group)

答案 2 :(得分:0)

尝试一下:

library(dplyr)
mylist <- list(a = c(1,2,3), b = c(4,5,6,7))
bind_rows(lapply(names(mylist), function(x) tibble(grp = x, num = mylist[[x]])))
# A tibble: 7 x 2
  grp     num
  <chr> <dbl>
1 a         1
2 a         2
3 a         3
4 b         4
5 b         5
6 b         6
7 b         7

这本质上是一个基于lapply的解决方案,在该解决方案中,您遍历列表的名称,而不是单个列表元素本身。如果您喜欢在R底下做所有事情,请注意上面的内容等同于

do.call(rbind, lapply(names(mylist), function(x) data.frame(grp = x, num = mylist[[x]], stringsAsFactors = F)))

已经说过,tibble是data.frames的现代实现方式,它是首选的,与bind_rows构造相比,do.call(rbind...是首选。

关于第二个问题,请注意以下几点:

lapply(mylist, function(x) str(x))
 num [1:3] 1 2 3
 num [1:4] 4 5 6 7
....
lapply(mylist, function(x) names(x))
$a
NULL
$b
NULL

您在这里看到的是lapply内的函数获取mylist的元素。在这种情况下,可以使用数字矢量。就lapply内部调用的函数而言,它没有任何名称。要强调这一点,请考虑以下因素:

names(c(1,2,3))
NULL

是相同的:向量c(1,2,3)没有名称属性。