Как удалить строки во фрейме данных?


224

У меня есть фрейм данных с именем "mydata", который выглядит так:

   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 

Я хотел бы удалить строку 2,4,6. Например, вот так:

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

12
Кроме того, вы можете ознакомиться с некоторой общей терминологией для работы с данными. Обычно это называется подмножеством, которое, если вы будете искать в Google «r подмножество данных», вы попадете на очень полезную страницу UCLA R FAQ . Кстати, добро пожаловать в Stackoverflow!
A5C1D2H2I1M1N2O1R2T1

Добавлены некоторые дополнительные способы поднабора с использованием логических векторов, в дополнение к превосходному ответу @ mrdwab.
Пол Химстра

2
@ A5C1D2H2I1M1N2O1R2T1: Часто задаваемые вопросы UCLA для поднабора R перемещены. Теперь это здесь .
Майк Шеррилл 'Cat Recall'

Ответы:


340

Основная идея заключается в том, что вы формируете набор строк, которые хотите удалить, и сохраняете дополнение этого набора.

В R дополнение множества задается оператором '-'.

Итак, предположим, что data.frameназывается myData:

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

Конечно, не забудьте «переназначить», myDataесли вы хотите полностью удалить эти строки - в противном случае R просто печатает результаты.

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

59
Не забудьте отметить ,там! ;)
Стивен Джеурис

5
Что делать, если ваш фрейм данных только один столбец. Кажется, что отбрасывается вся структура и
выводится

6
@road_to_quantdom, добавьте drop = FALSEтуда.
A5C1D2H2I1M1N2O1R2T1

4
«В R дополнение набора задается оператором« - »» -> Это очень вводящая в заблуждение формулировка. Отрицательные индексы удаляются и все тут, понятия о дополнении нет. Если вы работаете с логическим и пытаетесь использовать -его, он не будет работать, потому что оператор дополнения для логики есть !. Дополнение c (2,4,6) в строках, скорее всего, было бы setdiff (c (2,4,6), 1: nrow (myData)), которое не является c (-2, -4, -6) , хотя оба будут давать одинаковые строки при использовании с [.
asac

2
@Speldosa, myData[-c(2, 4, 6),,drop=F]. На самом деле, я хотел бы предложить, чтобы вы всегда вставляли ,drop=Fнепосредственно перед ]любым матричным доступом.
Аарон МакДейд

82

Вы также можете работать с так называемым логическим вектором, иначе logical:

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

Обратите внимание, что !оператор действует как НЕ, то есть !TRUE == FALSE:

myData = myData[!row_to_keep,]

Это кажется немного громоздким по сравнению с ответом @ mrwab (+1 btw :)), но логический вектор может быть сгенерирован на лету, например, когда значение столбца превышает определенное значение:

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

Вы можете преобразовать логический вектор в вектор индексов:

row_to_keep = which(myData$A > 4)

Наконец, очень интересный трюк заключается в том, что вы можете использовать этот вид поднабора не только для извлечения, но и для назначения:

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

где столбец Aназначен NA(не число), где Aпревышает 4.


Что если вы хотите исключить их? В вашем примере № 3, если вы ослабеваете
GabrielMontenegro

61

Проблемы с удалением по номеру строки

Для быстрого и грязного анализа вы можете удалить строки data.frame по номерам согласно верхнему ответу. То есть,

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

Однако, если вы пытаетесь написать надежный сценарий анализа данных, вам, как правило, следует избегать удаления строк по числовой позиции. Это связано с тем, что в будущем порядок строк в ваших данных может измениться. Общий принцип таблиц data.frame или базы данных заключается в том, что порядок строк не должен иметь значения. Если порядок имеет значение, это должно быть закодировано в фактической переменной в data.frame.

Например, представьте, что вы импортировали набор данных и удалили строки по числовой позиции после проверки данных и определения номеров строк, которые вы хотите удалить. Однако в какой-то момент вы переходите к необработанным данным, осматриваетесь и переупорядочиваете данные. Ваш код удаления строк теперь удалит неправильные строки, и, что еще хуже, вы вряд ли получите какие-либо ошибки, предупреждающие вас о том, что это произошло.

Лучшая стратегия

Лучшая стратегия состоит в том, чтобы удалять строки на основе существенных и стабильных свойств строки. Например, если у вас есть idпеременная столбца, которая однозначно идентифицирует каждый случай, вы можете использовать это.

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

В других случаях у вас будут формальные критерии исключения, которые можно указать, и вы можете использовать один из многих инструментов поднабора в R для исключения случаев, основанных на этом правиле.


11

Создайте столбец id в вашем фрейме данных или используйте любое имя столбца для идентификации строки. Использование индекса несправедливо для удаления.

Используйте subsetфункцию для создания нового кадра.

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

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

9

По упрощенной последовательности:

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

По последовательности:

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

По негативной последовательности:

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

Или, если вы хотите поднабор, выбрав нечетные числа:

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

Или, если вы хотите установить подмножество, выбрав нечетные числа, версия 2:

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

Или, если вы хотите установить подмножество, отфильтровывая четные числа:

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

Или, если вы хотите установить подмножество, отфильтровывая четные числа, версия 2:

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

5

Удалить Dan из employee.data - Нет необходимости управлять новым data.frame.

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

0

Вот быстрая и грязная функция для удаления строки по индексу.

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), ])
  }
}

Его главный недостаток в том, что аргумент row_index не следует шаблону R, являющемуся вектором значений. Могут быть и другие проблемы, поскольку я потратил всего пару минут на написание и тестирование и начал использовать R только в последние несколько недель. Любые комментарии и улучшения по этому поводу будут очень приветствоваться!


0

Для полноты добавлю, что это можно сделать и с dplyrпомощью slice. Преимущество использования этого в том, что он может быть частью конвейерного рабочего процесса.

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

Конечно, вы также можете использовать его без труб.

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

Формат «не вектор» -c(2, 4, 6)означает получение всего, что не находится в строках 2, 4 и 6. Например, для диапазона, например, вы хотите удалить первые 5 строк slice(df, 6:n()). Дополнительные примеры см. В документации .

Используя наш сайт, вы подтверждаете, что прочитали и поняли нашу Политику в отношении файлов cookie и Политику конфиденциальности.
Licensed under cc by-sa 3.0 with attribution required.