使用[按名称删除列,而无需为数据框/矩阵对象分配名称

时间:2018-09-09 06:47:23

标签: r

@Joris Meys great answer to this famous question建议使用名称列表按名称删除列。它要求事先为数据帧/矩阵分配一个名称,并使用names(df),或者为矩阵colnames(matrix)分配一个名称。

出于好奇,我想知道如果不首先为数据框/矩阵分配名称,是否可以采用类似的策略。我正在考虑on answering this question这个事实(从那里我刻划了示例数据)。

我建议的解决方案如下删除带有select的列:

bind_cols(split(df$b, df$year)) %>% select(-'1997')

我首先尝试使用do.call(cbind, split(df$b, df$year))来代替,但是这给出了一个矩阵,而dplyr::select不喜欢这样。现在我当然可以肯定选择

do.call(cbind, split(df$b, df$year))[,c('1996','1998')]

我也可以使用subset

subset(do.call(cbind, split(df$b, df$year)), select = - `1997`)

我的问题是如何使用[来按名称进行“否定选择”(此处:删除1997),而无需事先分配矩阵/数据框,即在一个衬里中。


数据

set.seed(77)
df <- data.frame(year = rep(1996:1998,3), a = runif(9), b = runif(9), e = runif(9))

# required result something like: (result from code above)   

          1996      1998
[1,] 0.4569087 0.9881951
[2,] 0.1658851 0.4475605
[3,] 0.3647157 0.7033574

2 个答案:

答案 0 :(得分:1)

显然有很多方法可以实现,但是如果您只想按名称使用负子集,那么一种方法是使用原始数据框来获取目标的第一个位置,然后使用该数据将其删除,即< / p>

do.call(cbind, split(df$b, df$year))[,-which(df$year == '1997')[1]]

给出,

          1996      1998
[1,] 0.4569087 0.9881951
[2,] 0.1658851 0.4475605
[3,] 0.3647157 0.7033574

注意1:您的初始数据帧必须在year上排序

注2::您可以使用cbind.data.frame将输出作为数据框

答案 1 :(得分:0)

这不会按名称选择列,但是如果您首先使用split进行否定选择来过滤[中的行怎么办?

do.call(cbind, split(df[-which(df$year == 1997),"b"], df[-which(df$year == 1997), "year"]))
#>           1996      1998
#> [1,] 0.4569087 0.9881951
#> [2,] 0.1658851 0.4475605
#> [3,] 0.3647157 0.7033574

或者是用于负列索引的超长单行

do.call(cbind, split(df$b, df$year))[,-which(colnames(do.call(cbind, split(df$b, df$year))) == "1997")]
#>           1996      1998
#> [1,] 0.4569087 0.9881951
#> [2,] 0.1658851 0.4475605
#> [3,] 0.3647157 0.7033574

尽管如此,您可以用管道将其冷凝

do.call(cbind, split(df$b, df$year)) %>%  .[,-which(colnames(.) == "1997")]
#>           1996      1998
#> [1,] 0.4569087 0.9881951
#> [2,] 0.1658851 0.4475605
#> [3,] 0.3647157 0.7033574