#r #dplyr #duplicates #data-manipulation
#r #dplyr #дубликаты #манипулирование данными
Вопрос:
Я работаю с языком программирования R. У меня есть следующая таблица:
age=18:29 height=c(76.1,77,78.1,78.2,78.8,79.7,79.9,81.1,81.2,81.8,82.8,83.5) gender=c("M","F","M","M","F","F","M","M","F","M","F","M") testframe = data.frame(age=age,height=height,height2=height,gender=gender,gender2=gender) head(testframe) age height height2 gender gender2 1 18 76.1 76.1 M M 2 19 77.0 77.0 F F 3 20 78.1 78.1 M M 4 21 78.2 78.2 M M 5 22 78.8 78.8 F F 6 23 79.7 79.7 F F
В приведенной выше таблице я хочу удалить столбцы с одинаковыми записями, но с разными именами. Это можно сделать следующим образом (в базе R):
no_dup = testframe[!duplicated(as.list(testframe))] head(no_dup) age height gender 1 18 76.1 M 2 19 77.0 F 3 20 78.1 M 4 21 78.2 M 5 22 78.8 F 6 23 79.7 F
Мой вопрос: Кто-нибудь знает, как преобразовать приведенный выше код testframe[!duplicated(as.list(testframe))
в команды «DPLYR»? Возможно ли это?
Спасибо!
Комментарии:
1. Вы можете передать его по каналу:
testframe %gt;% filter(. %gt;% as.list %gt;% duplicated %gt;% `!`)
, но это тот случай , когда имеет смысл использовать фрейм данных как alist
иdplyr
предназначен для рабочих фреймов данных, а не списков.2. @ Gregor Thomas: Спасибо за ваш ответ! Я попробую это сделать!
3. Но я отмечу, что код в моем комментарии несколько ироничен. Кроме трубопроводов (большая часть которых все еще вложена!), единственным изменением является замена
[
наfilter
.4. @ Gregor Thomas: Спасибо за ваш ответ! Как вы думаете, почему код в вашем комментарии в «несколько насмешливый:? Я не уверен, что вы имеете в виду во втором предложении — если у вас есть время, не могли бы вы, пожалуйста, показать мне, о какой замене вы говорите? Спасибо!
5. Хммм, я думаю
.
, это так не работает. Мой «насмешливый» комментарий связан с тем , что почти все, что я сделал, это изменил!duplicated(as.list())
as.list %gt;% duplicated %gt;% `!`
, который по-прежнему не использует никакихdplyr
функций. Таким образом, он использует трубопроводы изmagrittr
пакета, но единственнойdplyr
функцией, которую я (пытался) использовать, былаfilter
.
Ответ №1:
Вот один из вариантов использования tidyverse
. Я purrr::map
преобразовывал каждый столбец в список, а затем находил списки, которые не дублировались. Поскольку dplyr::select
вы не можете использовать логический вектор , поэтому мы можем использовать which
для возврата только TRUE
столбцы (т. е. не дублированные). Затем мы можем использовать значение индекса для выбора столбцов.
library(tidyverse) testframe %gt;% dplyr::select(., which(purrr::map(., c) %gt;% duplicated(.) %gt;% `!`))
Выход
age height gender 1 18 76.1 M 2 19 77.0 F 3 20 78.1 M 4 21 78.2 M 5 22 78.8 F 6 23 79.7 F 7 24 79.9 M 8 25 81.1 M 9 26 81.2 F 10 27 81.8 M 11 28 82.8 F 12 29 83.5 M
Вы также могли бы обойтись без purrr
этого .
testframe %gt;% dplyr::select(., which(as.list(.) %gt;% duplicated %gt;% `!`))
Просто для удовольствия, здесь я использую только tidyverse
(хотя и гораздо более подробно). Это также требует многократного поворота фрейма данных.
testframe %gt;% tibble::rownames_to_column() %gt;% dplyr::mutate_all(as.character) %gt;% tidyr::pivot_longer(-rowname) %gt;% tidyr::pivot_wider(names_from = rowname, values_from = value) %gt;% dplyr::distinct_at(vars(-name), .keep_all = TRUE) %gt;% tidyr::pivot_longer(-name, names_to = "rowname", values_to = "value") %gt;% tidyr::pivot_wider(names_from = name, values_from = value) %gt;% dplyr::select(-rowname)
Данные
testframe lt;- structure( list( age = 18:29, height = c(76.1, 77, 78.1, 78.2, 78.8, 79.7, 79.9, 81.1, 81.2, 81.8, 82.8, 83.5), height2 = c(76.1, 77, 78.1, 78.2, 78.8, 79.7, 79.9, 81.1, 81.2, 81.8, 82.8, 83.5), gender = c("M", "F", "M", "M", "F", "F", "M", "M", "F", "M", "F", "M"), gender2 = c("M", "F", "M", "M", "F", "F", "M", "M", "F", "M", "F", "M") ), class = "data.frame", row.names = c(NA, -12L) )
Комментарии:
1. @ Andrew Gillreath-Brown : Большое вам спасибо за ваш ответ! Я передал свой код с помощью «командной DBPLYR»: перелета lt;- copy_to(Con, то testframe) ; рейсах %gt;% dplyr::Select (в., который(как.перечень(.) %gt;% дублируется %gt;%
!
)) %gt;% show_query()2. Это возвращает следующую инструкцию SQL, соответствующую написанному вами коду (по какой-то причине отсутствует переменная «пол»): ВЫБЕРИТЕ
age
,height
ИЗtestframe
3. В конечном счете, я хочу использовать этот код в таблице, расположенной на сервере:
4. библиотека(RODBC); библиотека(sqldf); con = odbcConnect(«какое-то имя», uid = «какой-то идентификатор», pwd = «abc»); sample_query = SqlQuery(con, «ВЫБЕРИТЕ возраст, рост ИЗ тестового кадра»)
5. @stats555 Я только что добавил еще одну возможность (хотя она гораздо более подробна). По сути, это требует многократного поворота данных, что позволяет использовать
dplyr::distinct
их, а не использоватьduplicated
. Возможно , у него было бы лучшее преобразованиеDBPLYR
, но я не уверен.