@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
答案 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