R dplyr: eliminar várias colunas

96

Eu tenho um dataframe e uma lista de colunas nesse dataframe que gostaria de descartar. Vamos usar o irisconjunto de dados como exemplo. Eu gostaria de deixar cair Sepal.Lengthe Sepal.Widthe utilizar apenas as colunas restantes. Como faço isso usando selectou select_do dplyrpacote?

Aqui está o que tentei até agora:

drop.cols <- c('Sepal.Length', 'Sepal.Width')
iris %>% select(-drop.cols)

Erro em -drop.cols: argumento inválido para operador unário

iris %>% select_(.dots = -drop.cols)

Erro em -drop.cols: argumento inválido para operador unário

iris %>% select(!drop.cols)

Erro em! Drop.cols: tipo de argumento inválido

iris %>% select_(.dots = !drop.cols)

Erro em! Drop.cols: tipo de argumento inválido

Sinto que estou perdendo algo óbvio, porque parece uma operação muito útil que já deveria existir. No Github, alguém postou um problema semelhante , e Hadley disse para usar 'indexação negativa'. Isso é o que (eu acho) eu tentei, mas sem sucesso. Alguma sugestão?

Navaneethan Santhanam
fonte

Respostas:

127

Verifique a ajuda em select_vars. Isso lhe dá algumas idéias extras sobre como trabalhar com isso.

No seu caso:

iris %>% select(-one_of(drop.cols))
Phiver
fonte
Obrigado. Por alguma razão, isso funciona iris, mas não no meu dataframe real ( irisfoi um exemplo de brinquedo). Meu dataframe contém 4558 linhas e 147 colunas. A mensagem de erro que recebi foi Error in eval(x$expr, data, x$env) : variable names are limited to 10000 bytes. Alguma ideia de por que isso pode estar acontecendo?
Navaneethan Santhanam
1
Ah, parece que eu estava cometendo um erro. Eu usei acidentalmente em select_varsvez de select. Agora funciona perfeitamente!
Navaneethan Santhanam
5
Onde devemos encontrar informações sobre funções embutidas como one_of? A menos que esteja faltando alguma coisa, ela não aparece na documentação do pacote ( help(package='dplyr')).
geotheory
4
@geotheory, na verdade one_of está documentado. veja help(one_of, package = "dplyr"). Pelo menos está na versão do pacote 0.5.0. Mas ajuda ler os blogs que Hadley posta quando há atualizações em um de seus pacotes. E algumas funções são documentadas dentro de outras funções. Infelizmente, isso exige a leitura de toda a documentação, o que eu faço principalmente quando quero algo que não é imediatamente óbvio ou possível com a função.
phiver
10
Obrigado. Como você descobre essas funções em primeiro lugar, em termos de documentação?
geotheory
67

tente também

## Notice the lack of quotes
iris %>% select (-c(Sepal.Length, Sepal.Width))
Miguel Rayon Gonzalez
fonte
5
Ótimo! Muito útil quando temos que descartar colunas copiando e colando os nomes do console.
Pablo Casas de
37

Além select(-one_of(drop.cols))disso, há algumas outras opções para descartar colunas select()que não envolvem a definição de todos os nomes de coluna específicos (usando os dados de amostra do dplyr starwars para mais variedade de nomes de coluna):

starwars %>% 
  select(-(name:mass)) %>%        # the range of columns from 'name' to 'mass'
  select(-contains('color')) %>%  # any column name that contains 'color'
  select(-starts_with('bi')) %>%  # any column name that starts with 'bi'
  select(-ends_with('er')) %>%    # any column name that ends with 'er'
  select(-matches('^f.+s$')) %>%  # any column name matching the regex pattern
  select_if(~!is.list(.)) %>%     # not by column name but by data type
  head(2)

# A tibble: 2 x 2
homeworld species
  <chr>     <chr>  
1 Tatooine  Human  
2 Tatooine  Droid 
sbha
fonte
É select_if(~!is.list(.))equivalente a select_if(is.list(.))?
Jasha
3
Neste caso, ~é uma abreviatura de purrr para definir uma função anônima, não é outro símbolo para não. Por exemplo, esses dois significam a mesma coisa function(x) {!is.list(x)}e ~!is.list(.). pense ~em uma abreviação de function(.).
SlyFox
8

Tenha cuidado com a select()função, porque ela é usada nos pacotes dplyr e MASS, então se o MASS estiver carregado, select () pode não funcionar corretamente. Para descobrir quais pacotes estão carregados, digite sessionInfo()e procure por ele na seção "outros pacotes anexados:". Se estiver carregado, digite detach( "package:MASS", unload = TRUE )e sua select()função deverá funcionar novamente.

Durand Sinclair
fonte
12
como alternativa, você pode acessar a função diretamente no namespace do pacote dplyr::select().
Triamus
2
Já me deparei com esse problema com muita frequência. Agora geralmente defino uma nova função no início do meu script dselect <- dplyr::select().
filups
5

Nós podemos tentar

iris %>% 
      select_(.dots= setdiff(names(.),drop.cols))
Akrun
fonte
Obrigado @akrun, funcionou perfeitamente. No entanto, dada a dplyrcapacidade do hype em torno de tornar as tarefas de análise básicas fáceis de ler e escrever, estou desapontado que a solução real parece uma solução alternativa.
Navaneethan Santhanam
@NavaneethanSanthanam Na verdade, a one_ofoutra solução é o caminho a percorrer. Eu esqueci sobre isto.
akrun,
3

Outra maneira é transformar as colunas indesejadas em NULL, isso evita os parênteses incorporados:

head(iris,2) %>% mutate_at(drop.cols, ~NULL)
#   Petal.Length Petal.Width Species
# 1          1.4         0.2  setosa
# 2          1.4         0.2  setosa
Moody_Mudskipper
fonte
Isso também não dá um aviso se uma coluna não estiver lá.
skoz
3

Se você tiver um caractere especial nos nomes das colunas, um selectou outro select_pode não funcionar conforme o esperado. Esta propriedade dplyrde usar ".". Para referir-se ao conjunto de dados na pergunta, a seguinte linha pode ser usada para resolver este problema:

drop.cols <- c('Sepal.Length', 'Sepal.Width')
  iris %>% .[,setdiff(names(.),drop.cols)]
Dineshram Mattapalli
fonte
Respostas apenas em código são desencorajadas. Forneça algumas explicações sobre como a resposta funciona e como ela difere das respostas já presentes.
Ralf Stubner
Obrigado!! Nenhuma das outras soluções acima funcionou exatamente por esse motivo.
Marty999
0

Podes tentar

iris %>% select(-!!drop.cols)
Canhoto
fonte