row.names(x)与row.names〈- in l应用于数据框列表

hjzp0vay  于 2023-01-18  发布在  其他
关注(0)|答案(1)|浏览(132)

当我试图回答这个问题时,我注意到在 Dataframe 列表上使用lapplyrow.names(x) <- vector不起作用,而row.names<-起作用。
下面是一些示例数据,我尝试将列表的names附加到 Dataframe 的rownames

l <- list(a=data.frame(col = c(1,2,3),row.names = c("k","l","m")), 
          b=data.frame(col = c(4,5,6), row.names = c("o","p","r")))

$a
  col
k   1
l   2
m   3

$b
  col
o   4
p   5
r   6

例如,当循环遍历列表的names并在lapply中设置row.names时,结果如下:

lapply(names(l), \(x) row.names(l[[x]]) <- paste0(x, ".", rownames(l[[x]])))

[[1]]
[1] "a.k" "a.l" "a.m"

[[2]]
[1] "b.o" "b.p" "b.r"

当我们在lapply之外执行相同的代码时,它工作了:

> row.names(l[["a"]]) <- paste0("a.", rownames(l[["a"]]))
> l

$a
    col
a.k   1
a.l   2
a.m   3

我对这个问题的解决方案是使用row.names<-(正如原始OP所建议的):

setNames(lapply(names(l), 
                \(x) l[[x]] %>% `row.names<-` (paste(x, rownames(l[[x]]), sep = "."))), 
         names(l))

$a
    col
a.k   1
a.l   2
a.m   3

$b
    col
b.o   4
b.p   5
b.r   6

但是我不确定为什么row.names(x) <- vector语法失败,为什么row.names<-工作。

jhkqcmku

jhkqcmku1#

  • 赋值是 local,也就是说,它在匿名函数 * 内部 * 创建了一个modified对象l,并为其分配了行名称。
  • <-赋值的 result 从匿名函数返回,但是<-的结果 * 总是 * RHS,即使对于替换函数也是如此,你可以通过在全局作用域中用括号括住赋值来使其可见:
(row.names(l$a) <- paste0('a.', row.names(l$a)))
# [1] "a.k" "a.l" "a.m"

因此,在第二段代码中,lapply使用的转换只是赋值的结果,即赋值的RHS,即转换后的行名称。要修复代码,需要返回修改后的对象l[[x]]本身:

lapply(
    names(l),
    \(x) {
        row.names(l[[x]]) <- paste0(x, ".", row.names(l[[x]]))
        l[[x]]
    }
)

或者使用row.names<-作为函数调用:

lapply(names(l), \(x) `row.names<-`(l[[x]], paste0(x, ".", row.names(l[[x]]))))

为了使其更易于阅读,请使用Map代替lapply

Map(\(x, n) `row.names<-`(x, paste0(n, ".", row.names(x))), l, names(l))

或者,如果没有匿名函数(尽管我不认为这样更可读):

Map(`row.names<-`, l, Map(paste0, names(l), ".", Map(row.names, l)))

相关问题