R dplyr: Відкиньте кілька стовпців


96

У мене є фрейм даних та список стовпців у цьому фреймі даних, які я хотів би скинути. Давайте використаємо irisнабір даних як приклад. Я хотів би кинути Sepal.Lengthі Sepal.Widthі використовувати тільки залишилися стовпці. Як це зробити, використовуючи пакунок selectабо select_з нього dplyr?

Ось те, що я намагався дотепер:

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

Помилка в -drop.cols: недійсний аргумент для одинарного оператора

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

Помилка в -drop.cols: недійсний аргумент для одинарного оператора

iris %>% select(!drop.cols)

Помилка! Drop.cols: невірний тип аргументу

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

Помилка! Drop.cols: невірний тип аргументу

Я відчуваю, що пропускаю щось очевидне, оскільки це здається досить корисною операцією, яка вже мала б існувати. На Github хтось публікував подібну проблему , і Хедлі сказав використовувати "негативну індексацію". Ось що (я думаю) я намагався, але безрезультатно. Будь-які пропозиції?

Відповіді:


127

Перевірте довідку на select_vars. Це дає вам додаткові ідеї щодо того, як з цим працювати.

У вашому випадку:

iris %>% select(-one_of(drop.cols))

Дякую. З якоїсь причини це працює на iris, але не на моєму фактичному фреймі даних (це irisбув іграшковий приклад). Мій фрейм даних містить 4558 рядків і 147 стовпців. Повідомлення про помилку, яке я отримав, було Error in eval(x$expr, data, x$env) : variable names are limited to 10000 bytes. Будь-яка ідея, чому це може відбуватися?
Наванеетан Сантанам

1
Ах, схоже, я зробив помилку. Я випадково використав select_varsзамість select. Тепер це працює чудово!
Navaneethan Santhanam

5
Де ми маємо дізнатись про такі вбудовані функції one_of? Якщо я чогось не пропустив, це не відображається в документації до пакета ( help(package='dplyr')).
geotheory

4
@geotheory, насправді one_of задокументовано. див help(one_of, package = "dplyr"). Принаймні, це в пакетній версії 0.5.0. Але корисно читати блоги, які розміщує Хедлі, коли є оновлення одного з його пакетів. А деякі функції задокументовані всередині інших функцій. На жаль, для цього потрібно прочитати всю документацію, що я, в основному, роблю, коли хочу щось, що не одразу стає очевидним чи можливим з функцією.
Фівер

10
Дякую. Звідки ви дізнаєтесь про ці функції в першу чергу з точки зору документації?
geotheory


37

Окрім select(-one_of(drop.cols))цього, є ще кілька варіантів видалення стовпців за допомогою select(), які не передбачають визначення всіх конкретних імен стовпців (з використанням зразкових даних dplyr starwars для деякого різноманіття в назвах стовпців):

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 

Це select_if(~!is.list(.))еквівалентно select_if(is.list(.))?
Яша,

3
У цьому випадку ~це скорочення для визначення анонімної функції, це не інший символ для. Наприклад, ці два означають одне function(x) {!is.list(x)}і те ж і ~!is.list(.). розглядати ~як скорочення для function(.).
SlyFox

8

Будьте обережні з select()функцією, оскільки вона використовується як у пакетах dplyr, так і в MASS, тому, якщо MASS завантажено, select () може не працювати належним чином. Щоб дізнатись, які пакунки завантажені, введіть sessionInfo()та знайдіть його в розділі "інші вкладені пакунки:". Якщо він завантажений, введіть detach( "package:MASS", unload = TRUE ), і ваша select()функція повинна працювати знову.


12
або ж ви можете отримати доступ до функції безпосередньо у просторі імен пакунків dplyr::select().
Тріамус

2
Я стикався із цією проблемою занадто часто. Зараз я зазвичай визначаю нову функцію вгорі мого сценарію dselect <- dplyr::select().
filups21,

5

Ми можемо спробувати

iris %>% 
      select_(.dots= setdiff(names(.),drop.cols))

Дякую @akrun, це спрацювало чудово. Однак, враховуючи можливість галасливого оточення спрощувати dplyrчитання та запис основних завдань аналізу, я розчарований тим, що фактичне рішення виглядає як обхідний шлях.
Navaneethan Santhanam

@NavaneethanSanthanam Насправді, one_ofінше рішення - це шлях. Я про це забув.
akrun

3

Іншим способом є мутація небажаних стовпців NULL, це дозволяє уникнути вбудованих дужок:

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

Це також не дає попередження, якщо стовпця немає.
skoz

3

Якщо в іменах стовпців є спеціальний символ, він може працювати selectабо select_не працювати належним чином. Ця властивість dplyrвикористання ".". Для посилання на набір даних у питанні для вирішення цієї проблеми можна використати такий рядок:

drop.cols <- c('Sepal.Length', 'Sepal.Width')
  iris %>% .[,setdiff(names(.),drop.cols)]

Відповіді лише на код не рекомендується. Будь ласка, надайте пояснення щодо того, як працює відповідь та чим вона відрізняється від вже наявних відповідей.
Ральф Стубнер,

Дякую!! Жодне з інших наведених вище рішень не працювало саме з цієї причини.
Marty999

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.