Como faço para excluir linhas em um quadro de dados?

224

Eu tenho um quadro de dados chamado "mydata" que se parece com isto:

   A  B  C   D 
1. 5  4  4   4 
2. 5  4  4   4 
3. 5  4  4   4 
4. 5  4  4   4 
5. 5  4  4   4 
6. 5  4  4   4 
7. 5  4  4   4 

Eu gostaria de excluir a linha 2,4,6. Por exemplo, assim:

   A  B  C   D
1. 5  4  4  4 
3. 5  4  4  4 
5. 5  4  4  4 
7. 5  4  4  4 
R novato
fonte
12
Além disso, você pode se familiarizar com alguma terminologia comum para trabalhar com dados. Isto é normalmente referido como subsetting, que, se você procurou no Google por "quadro de dados r subconjunto" você iria chegar ao muito útil UCLA R FAQ página . Bem-vindo ao Stackoverflow, a propósito!
A5C1D2H2I1M1N2O1R2T1 08/09/12
Adicionadas algumas maneiras adicionais de subconjunto usando vetores booleanos, além da excelente resposta do @ mrdwab.
Paul Hiemstra 08/09/12
2
@ A5C1D2H2I1M1N2O1R2T1: As Perguntas frequentes da UCLA para subconjunto R foram movidas. Agora está aqui .
Mike Sherrill 'Cat Recall'

Respostas:

340

A idéia principal é formar um conjunto de linhas que você deseja remover e manter o complemento desse conjunto.

Em R, o complemento de um conjunto é dado pelo operador '-'.

Então, assumindo que o data.frameé chamado myData:

myData[-c(2, 4, 6), ]   # notice the -

Obviamente, não se esqueça de "reatribuir" myDatase você quiser eliminar completamente essas linhas - caso contrário, R apenas imprime os resultados.

myData <- myData[-c(2, 4, 6), ]
A5C1D2H2I1M1N2O1R2T1
fonte
59
Não se esqueça de observar o que está ,lá! ;)
Steven Jeuris
5
e se o seu quadro de dados for apenas uma coluna. Parece que a queda de toda a estrutura e gera um vector dos valores
road_to_quantdom
6
@road_to_quantdom, adicione um drop = FALSElá.
A5C1D2H2I1M1N2O1R2T1
4
"Em R, o complemento de um conjunto é dado pelo operador '-'" -> Esta é uma expressão muito enganadora. Índices negativos são removidos e é isso, não há noção de complemento. Se você trabalha com lógico e tenta usá- -lo, não funcionará, porque o operador de complemento para lógicos é !. O complemento de c (2,4,6) nas linhas prefere ser diferenciado (c (2,4,6), 1: nrow (myData)), que não é c (-2, -4, -6) , embora ambos produzam as mesmas linhas quando usados ​​com [.
As4
2
@Speldosa myData[-c(2, 4, 6),,drop=F],. Na verdade, eu sugiro que você sempre insira um ,drop=Fpouco antes do ]acesso a qualquer matriz.
Aaron McDaid
82

Você também pode trabalhar com o chamado vetor booleano, também conhecido como logical:

row_to_keep = c(TRUE, FALSE, TRUE, FALSE, TRUE, FALSE, TRUE)
myData = myData[row_to_keep,]

Observe que o !operador atua como um NÃO, ou seja !TRUE == FALSE:

myData = myData[!row_to_keep,]

Isso parece um pouco complicado em comparação com a resposta de @ mrwab (+1 btw :)), mas um vetor lógico pode ser gerado em tempo real, por exemplo, onde um valor de coluna excede um determinado valor:

myData = myData[myData$A > 4,]
myData = myData[!myData$A > 4,] # equal to myData[myData$A <= 4,]

Você pode transformar um vetor booleano em um vetor de índices:

row_to_keep = which(myData$A > 4)

Por fim, um truque muito interessante é que você pode usar esse tipo de subconjunto não apenas para extração, mas também para atribuição:

myData$A[myData$A > 4,] <- NA

onde a coluna Aé atribuída NA(não um número) onde Aexcede 4.

Paul Hiemstra
fonte
E se você quiser excluí-los? No seu exemplo número 3, se você diminuir
GabrielMontenegro 15/09
61

Problemas com a exclusão pelo número da linha

Para análises rápidas e sujas, você pode excluir as linhas de um data.frame por número, conforme a resposta principal. Ou seja,

newdata <- myData[-c(2, 4, 6), ] 

No entanto, se você estiver tentando escrever um script de análise de dados robusto, geralmente evite excluir linhas por posição numérica. Isso ocorre porque a ordem das linhas nos seus dados pode mudar no futuro. Um princípio geral de uma tabela data.frame ou banco de dados é que a ordem das linhas não deve importar. Se o pedido importa, isso deve ser codificado em uma variável real no data.frame.

Por exemplo, imagine que você importou um conjunto de dados e excluiu linhas por posição numérica após inspecionar os dados e identificar os números das linhas que você deseja excluir. No entanto, em algum momento posterior, você acessa os dados brutos, dá uma olhada e reordena os dados. Seu código de exclusão de linha agora excluirá as linhas incorretas e, pior ainda, é improvável que você receba algum erro avisando que isso ocorreu.

Melhor estratégia

Uma estratégia melhor é excluir linhas com base nas propriedades substantivas e estáveis ​​da linha. Por exemplo, se você tiver uma idvariável de coluna que identifique exclusivamente cada caso, poderá usá-la.

newdata <- myData[ !(myData$id %in% c(2,4,6)), ]

Outras vezes, você terá um critério de exclusão formal que pode ser especificado e poderá usar uma das muitas ferramentas de subconjunto no R para excluir casos com base nessa regra.

Jeromy Anglim
fonte
11

Crie uma coluna de identificação no seu quadro de dados ou use qualquer nome de coluna para identificar a linha. Usar o índice não é justo para excluir.

Use a subsetfunção para criar um novo quadro.

updated_myData <- subset(myData, id!= 6)
print (updated_myData)

updated_myData <- subset(myData, id %in% c(1, 3, 5, 7))
print (updated_myData)
Paranthaman Ramakrishnan
fonte
9

Por sequência simplificada:

mydata[-(1:3 * 2), ]

Por sequência:

mydata[seq(1, nrow(mydata), by = 2) , ]

Por sequência negativa:

mydata[-seq(2, nrow(mydata), by = 2) , ]

Ou se você deseja subconjunto selecionando números ímpares:

mydata[which(1:nrow(mydata) %% 2 == 1) , ]

Ou, se desejar subconjunto, selecionando números ímpares, versão 2:

mydata[which(1:nrow(mydata) %% 2 != 0) , ]

Ou se você deseja subconjunto, filtrando números pares:

mydata[!which(1:nrow(mydata) %% 2 == 0) , ]

Ou, se você deseja fazer um subconjunto filtrando números pares, versão 2:

mydata[!which(1:nrow(mydata) %% 2 != 1) , ]
Elías De La Rosa
fonte
5

Exclua Dan de employee.data - Não há necessidade de gerenciar um novo data.frame.

employee.data <- subset(employee.data, name!="Dan")
SQLWolfe
fonte
0

Aqui está uma função rápida e suja para remover uma linha por índice.

removeRowByIndex <- function(x, row_index) {
  nr <- nrow(x)
  if (nr < row_index) {
    print('row_index exceeds number of rows')
  } else if (row_index == 1)
  {
    return(x[2:nr, ])
  } else if (row_index == nr) {
    return(x[1:(nr - 1), ])
  } else {
    return (x[c(1:(row_index - 1), (row_index + 1):nr), ])
  }
}

Sua principal falha é que o argumento row_index não segue o padrão R de ser um vetor de valores. Pode haver outros problemas, pois passei apenas alguns minutos escrevendo e testando-o e só comecei a usar o R ​​nas últimas semanas. Quaisquer comentários e melhorias sobre isso serão muito bem-vindos!

Alan Carlyle
fonte
0

Para completar, acrescentarei que isso também pode ser feito com o dplyruso slice. A vantagem de usar isso é que ele pode fazer parte de um fluxo de trabalho canalizado.

df <- df %>%
  .
  .
  slice(-c(2, 4, 6)) %>%
  .
  .

Claro, você também pode usá-lo sem tubos.

df <- slice(df, -c(2, 4, 6))

O formato "não vetorial" -c(2, 4, 6)significa obter tudo o que não está nas linhas 2, 4 e 6. Por exemplo, usando um intervalo, digamos que você queira remover as 5 primeiras linhas, você pode fazer isso slice(df, 6:n()). Para mais exemplos, consulte os documentos .

Ryan H.
fonte