从 data.frame 中提取单行而不丢失名称

Extracting single row from data.frame without loss of names

我只是从 data.frame 中提取一行。考虑例如

d=data.frame(a=1:3,b=1:3)
d[1,]    # returns a data.frame
#   a b
# 1 1 1

结果符合我的预期。尽管在处理包含单列的 data.frame 时,结果并不像我预期的那样。

d=data.frame(a=1:3)
d[1,]   # returns an integer
# [1] 1

确实,在这里,提取的数据不再是data.frame,而是integer!对我来说,同一数据类型上的同一函数想要 return 不同的数据类型似乎有点奇怪。此转换的问题之一是列名丢失。

为了解决这个问题,我做了

extractRow = function(d,index)
{
    if (ncol(d) > 1)
    {
        return(d[index,])
    } else
    {
        d2 = as.data.frame(d[index,])
        names(d2) = names(d)
        return(d2)
    }
}

d=data.frame(a=1:3,b=1:3)
extractRow(d,1)
#   a b    
# 1 1 1

d=data.frame(a=1:3)
extractRow(d,1)
#   a
# 1 1

但这似乎是不必要的麻烦。有更好的解决方案吗?

我不能告诉你为什么会这样——这看起来很奇怪。一种解决方法是使用 dplyr 中的 slice(尽管使用库对于这样一个简单的任务似乎是不必要的)。

library(dplyr)
slice(d, 1)
  a
1 1

只是带有 drop = FALSE 选项的子集:

extractRow = function(d, index) {
    return(d[index, , drop=FALSE])
}

R 尝试默认简化 data.frame 切割,同样的事情发生在列上:

d[, "a"]

# [1] 1 2 3

备选方案是:

  • d[1, , drop = FALSE]
  • tibble::tibble 默认情况下有 drop = FALSE

data.frames 将简化为具有基本子集 [,].

的向量或标量

如果您想避免这种情况,您可以改用 tibbles:

> tibble(a=1:2)[1,]

# A tibble: 1 x 1
      a
  <int>
1     1

tibble(a=1:2)[1,] %>% class
[1] "tbl_df"     "tbl"        "data.frame"