Как удалить столбцы из data.frame? - PullRequest
37 голосов
/ 16 августа 2011

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

Если у вас есть файл, который кто-то дает вам с 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",...)]

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

EDIT:

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

Ответы [ 11 ]

54 голосов
/ 16 августа 2011

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

DT[, coltodelete := NULL]

или

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

или

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

или

DT[, (variableHoldingNamesOrNumbers) := NULL]

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

31 голосов
/ 16 августа 2011

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

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

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

subset(mtcars, , -c(mpg, cyl, disp, hp))
9 голосов
/ 16 августа 2011

Для ясности я часто использую аргумент 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
....

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

7 голосов
/ 16 августа 2011

Используйте 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 голосов
/ 16 августа 2011

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

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

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

3 голосов
/ 16 августа 2011

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

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"))
2 голосов
/ 07 января 2017

С 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

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

1 голос
/ 29 января 2017

Функция 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")
1 голос
/ 21 июля 2016

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

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
1 голос
/ 01 октября 2014

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

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

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

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

DT<-DT[,c("col1","col2")]
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...