Как удалить столбцы из data.frame?

Не так много "Как вы...?" но больше "Как вы...?"

Если у вас есть файл, кто-то дает вам 200 столбцов, и вы хотите уменьшить его до нескольких, которые вам нужны для анализа, как вы это делаете? Предоставляет ли одно решение преимущество над другим?

Предполагая, что у нас есть кадр данных с столбцами col1, col2 и col200. Если вам нужны только 1-100, а затем 125-135 и 150-200, вы можете:

dat$col101 <- NULL
dat$col102 <- NULL # etc

или

dat <- dat[,c("col1","col2",...)]

или

dat <- dat[,c(1:100,125:135,...)] # shortest probably but I don't like this

или

dat <- dat[,!names(dat) %in% c("dat101","dat102",...)]

Что-нибудь еще мне не хватает? Я знаю, что это зрелище субъективно, но это одна из тех мелочей, где вы можете погрузиться и начать делать это одним способом и впадать в привычку, когда есть более эффективные пути. Как и этот вопрос о which.

EDIT:

Или существует ли простой способ создания работоспособного вектора имен столбцов? name (dat) не печатает их с запятыми между ними, которые вам нужны в приведенных выше примерах кода, поэтому, если вы распечатываете имена таким образом, у вас есть места повсюду и их нужно вручную вводить запятыми... Есть ли команда, которая даст вам "col1", "col2", "col3",... как ваш вывод, чтобы вы могли легко захватить то, что хотите?

Ответ 1

Я использую data.table := оператор для немедленного удаления столбцов независимо от размера таблицы.

DT[,coltodelete:=NULL]

или

DT[,c("col1","col20"):=NULL]

или

DT[,(125:135):=NULL]

или

DT[,(variableHoldingNamesOrNumbers):=NULL]

Любое решение, использующее <- или subset, скопирует всю таблицу. data.table := оператор просто модифицирует внутренний вектор указателей на столбцы, на месте. Таким образом, эта операция (почти) мгновенно.

Ответ 2

Чтобы удалить отдельные столбцы, я просто использую dat$x <- NULL.

Чтобы удалить несколько столбцов, но менее 3-4, я буду использовать dat$x <- dat$y <- dat$z <- NULL.

Более того, я буду использовать subset с отрицательными именами (!):

subset(mtcars, , -c(mpg, cyl, disp, hp))

Ответ 3

Для ясности я часто использую аргумент select в subset. С новыми людьми я узнал, что сохранить # команд, которые им нужно, чтобы поднять до минимума, помогает усыновить. По мере того, как повышается их квалификация, их способность кодирования тоже будет. Подмножество - одна из первых команд, которые я показываю людям, когда вам нужно выбирать данные в рамках заданного критерия.

Что-то вроде:

> subset(mtcars, select = c("mpg", "cyl", "vs", "am"))
                     mpg cyl vs am
Mazda RX4           21.0   6  0  1
Mazda RX4 Wag       21.0   6  0  1
Datsun 710          22.8   4  1  1
....

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

Ответ 4

Используйте read.table с экземплярами colClasses "NULL", чтобы избежать их создания в первую очередь:

## example data and temp file
x <- data.frame(x = 1:10, y = rnorm(10), z = runif(10), a = letters[1:10], stringsAsFactors = FALSE)
tmp <- tempfile()
write.table(x, tmp, row.names = FALSE)


(y <- read.table(tmp, colClasses = c("numeric", rep("NULL", 2), "character"), header = TRUE))

x a
1   1 a
2   2 b
3   3 c
4   4 d
5   5 e
6   6 f
7   7 g
8   8 h
9   9 i
10 10 j

unlink(tmp)

Ответ 5

Для типов больших файлов, которые я обычно получаю, я вообще не делал этого в R. Я бы использовал команду cut в Linux для обработки данных до того, как добрался до Р. Это не критика из R, просто предпочтение использовать некоторые очень простые инструменты Linux, такие как grep, tr, cut, sort, uniq и иногда sed и awk (или Perl), когда что-то нужно делать с регулярными выражениями.

Другая причина использования стандартных команд GNU заключается в том, что я могу передать их обратно источнику данных и попросить их предварительно фильтровать данные, чтобы я не получал посторонние данные. Большинство моих коллег компетентны в Linux, меньше знают R.

(Обновлено). Метод, который я хотел бы использовать в ближайшее время, - это пара mmap с текстовым файлом и изучить данные на месте, а не читать его вообще в ОЗУ. Я сделал это с помощью C, и это может быть очень быстро.

Ответ 6

Иногда мне нравится делать это с помощью идентификаторов столбцов.

df <- data.frame(a=rnorm(100),
b=rnorm(100),
c=rnorm(100),
d=rnorm(100),
e=rnorm(100),
f=rnorm(100),
g=rnorm(100)) 

as.data.frame(имена (ДФ))

  names(df)
1         a
2         b
3         c
4         d
5         e
6         f
7         g 

Удаление столбцов "c" и "g"

df[,-c(3,7)]

Это особенно полезно, если у вас есть data.frames, которые являются большими или имеют длинные имена столбцов, которые вы не хотите вводить. Или имена столбцов, которые следуют шаблону, потому что тогда вы можете использовать seq() для удаления.

RE: Ваше редактирование

Вам необязательно ставить "вокруг строки" или "," для создания символьного вектора. Я нахожу этот небольшой трюк удобным:

x <- unlist(strsplit(
'A
B
C
D
E',"\n"))

Ответ 7

Просто обращается к редактированию.

@nzcoops, вам не нужны имена столбцов в символе символов с разделителями-запятыми. Вы думаете об этом неправильно. Когда вы делаете

vec <- c("col1", "col2", "col3")

вы создаете вектор символа. , просто разделяет аргументы, используемые функцией c() при определении этого вектора. names() и аналогичные функции возвращают символьный вектор имен.

> dat <- data.frame(col1 = 1:3, col2 = 1:3, col3 = 1:3)
> dat
  col1 col2 col3
1    1    1    1
2    2    2    2
3    3    3    3
> names(dat)
[1] "col1" "col2" "col3"

Гораздо проще и меньше ошибок подвергать выбор из элементов names(dat), чем обрабатывать его вывод в разделенную запятыми строку, которую вы можете вырезать и вставить.

Скажем, нам нужны столбцы col1 и col2, подмножество names(dat), сохраняющие только те, которые мы хотим:

> names(dat)[c(1,3)]
[1] "col1" "col3"
> dat[, names(dat)[c(1,3)]]
  col1 col3
1    1    1
2    2    2
3    3    3

Вы можете делать то, что хотите, но R всегда будет печатать вектор на экране в кавычках ":

> paste('"', names(dat), '"', sep = "", collapse = ", ")
[1] "\"col1\", \"col2\", \"col3\""
> paste("'", names(dat), "'", sep = "", collapse = ", ")
[1] "'col1', 'col2', 'col3'"

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

Ответ 8

Если у вас уже есть вектор имен, который можно создать несколькими способами, вы можете легко использовать функцию подмножества для сохранения или удаления объекта.

dat2 <- subset(dat, select = names(dat) %in% c(KEEP))

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

#sample data via Brandon Bertelsen
df <- data.frame(a=rnorm(100),
                 b=rnorm(100),
                 c=rnorm(100),
                 d=rnorm(100),
                 e=rnorm(100),
                 f=rnorm(100),
                 g=rnorm(100))

#creating the initial vector of names
df1 <- as.matrix(as.character(names(df)))

#retaining only the name values you want to keep
KEEP <- as.vector(df1[c(1:3,5,6),])

#subsetting the intial dataset with the object KEEP
df3 <- subset(df, select = names(df) %in% c(KEEP))

Результат:

> head(df)
            a          b           c          d
1  1.05526388  0.6316023 -0.04230455 -0.1486299
2 -0.52584236  0.5596705  2.26831758  0.3871873
3  1.88565261  0.9727644  0.99708383  1.8495017
4 -0.58942525 -0.3874654  0.48173439  1.4137227
5 -0.03898588 -1.5297600  0.85594964  0.7353428
6  1.58860643 -1.6878690  0.79997390  1.1935813
            e           f           g
1 -1.42751190  0.09842343 -0.01543444
2 -0.62431091 -0.33265572 -0.15539472
3  1.15130591  0.37556903 -1.46640276
4 -1.28886526 -0.50547059 -2.20156926
5 -0.03915009 -1.38281923  0.60811360
6 -1.68024349 -1.18317733  0.42014397

> head(df3)
        a          b           c           e
1  1.05526388  0.6316023 -0.04230455 -1.42751190
2 -0.52584236  0.5596705  2.26831758 -0.62431091
3  1.88565261  0.9727644  0.99708383  1.15130591
4 -0.58942525 -0.3874654  0.48173439 -1.28886526
5 -0.03898588 -1.5297600  0.85594964 -0.03915009
6  1.58860643 -1.6878690  0.79997390 -1.68024349
            f
1  0.09842343
2 -0.33265572
3  0.37556903
4 -0.50547059
5 -1.38281923
6 -1.18317733

Ответ 9

От http://www.statmethods.net/management/subset.html

# exclude variables v1, v2, v3
myvars <- names(mydata) %in% c("v1", "v2", "v3") 
newdata <- mydata[!myvars]

# exclude 3rd and 5th variable 
newdata <- mydata[c(-3,-5)]

# delete variables v3 and v5
mydata$v3 <- mydata$v5 <- NULL

Думал, что это действительно умный, сделать список "не включать"

Ответ 10

Может использовать функцию setdiff:

Если хранится больше столбцов, чем удалять: Предположим, вы хотите удалить. 2 столбца говорят col1, col2 из data.frame DT; вы можете сделать следующее:

DT<-DT[,setdiff(names(DT),c("col1","col2"))]

Если удалить больше столбцов, чем сохранить: Предположим, что вы хотите сохранить только col1 и col2:

DT<-DT[,c("col1","col2")]

Ответ 11

Функция select() от dplyr является мощной для подмножества столбцов. См. ?select_helpers для списка подходов.

В этом случае, когда у вас есть общий префикс и порядковые номера для имен столбцов, вы можете использовать num_range:

library(dplyr)

df1 <- data.frame(first = 0, col1 = 1, col2 = 2, col3 = 3, col4 = 4)
df1 %>%
  select(num_range("col", c(1, 4)))
#>   col1 col4
#> 1    1    4

В общем случае вы можете использовать знак минус в select() для удаления столбцов, например:

mtcars %>%
   select(-mpg, -wt)

Наконец, на ваш вопрос "есть ли простой способ создать работоспособный вектор имен столбцов?" - да, если вам нужно вручную отредактировать список имен, используйте dput, чтобы получить список с разделителями-запятыми, который вы можете легко манипулировать:

dput(names(mtcars))
#> c("mpg", "cyl", "disp", "hp", "drat", "wt", "qsec", "vs", "am", 
#> "gear", "carb")