Сортированный и упорядоченный кадр данных уникальных значений - PullRequest
0 голосов
/ 26 октября 2018

Вот игрушечные данные:

df <- tibble::tribble( ~var2, ~var1, ~var3,   ~var4,
                      2L,   "A",   1.2,  "1/6/2018",
                      4L,   "A",  1.34,  "1/3/2018",
                      7L,   "B",  2.43,  "1/7/2018",
                      3L,   "C",     4,  "1/4/2018",
                      7L,   "A",   3.2,  "1/9/2018",
                      3L,   "D",   2.3, "1/10/2018",
                      4L,   "A",  0.34,  "1/9/2018",
                      5L,   "C",   4.2,  "1/7/2018",
                      5L,   "D",   6.5, "1/10/2018") %>% 
      mutate(var4 = mdy(var4))

Я хочу создать фрейм данных с уникальными значениями каждой переменной в df, отсортированными от самых больших (вверху) к наименьшим значениям (внизу) и наоборот-верса для переменных даты.Также переменные должны быть упорядочены (слева направо) от наименее уникальных к большинству уникальных значений.Желаемое значение должно быть:

 df_of_unique_values <- tibble::tribble(~var1, ~var2,    ~var4,  ~var3,
                                        "D",    7L,  "1/3/2018",   6.5,
                                        "C",    5L,  "1/4/2018",   4.2,
                                        "B",    4L,  "1/6/2018",     4,
                                        "A",    3L,  "1/7/2018",   3.2,
                                         NA,    2L,  "1/9/2018",  2.43,
                                         NA,    NA, "1/10/2018",   2.3,
                                         NA,    NA,          NA,  1.34,
                                         NA,    NA,          NA,   1.2,
                                         NA,    NA,          NA,  0.34) %>% 
  mutate(var4 = mdy(var4))

Как я могу это сделать, предпочтительно используя tidyverse?

Ответы [ 2 ]

0 голосов
/ 26 октября 2018

Заимствование из Объединение списков различной длины во фрейм данных :

str(lists <- lapply(df, function(a) sort(unique(a), decreasing=!inherits(a,"Date"))))
# List of 4
#  $ var2: int [1:5] 7 5 4 3 2
#  $ var1: chr [1:4] "D" "C" "B" "A"
#  $ var3: num [1:9] 6.5 4.2 4 3.2 2.43 2.3 1.34 1.2 0.34
#  $ var4: Date[1:6], format: "2018-01-03" "2018-01-04" "2018-01-06" "2018-01-07" ...
str(lists <- lists[order(lengths(lists))])
# List of 4
#  $ var1: chr [1:4] "D" "C" "B" "A"
#  $ var2: int [1:5] 7 5 4 3 2
#  $ var4: Date[1:6], format: "2018-01-03" "2018-01-04" "2018-01-06" "2018-01-07" ...
#  $ var3: num [1:9] 6.5 4.2 4 3.2 2.43 2.3 1.34 1.2 0.34
(maxlen <- max(lengths(lists)))
# [1] 9
str(lists <- lapply(lists, function(l) c(l, rep(NA, maxlen-length(l)))))
# List of 4
#  $ var1: chr [1:9] "D" "C" "B" "A" ...
#  $ var2: int [1:9] 7 5 4 3 2 NA NA NA NA
#  $ var4: Date[1:9], format: "2018-01-03" "2018-01-04" "2018-01-06" "2018-01-07" ...
#  $ var3: num [1:9] 6.5 4.2 4 3.2 2.43 2.3 1.34 1.2 0.34
as.data.frame(lists)
#   var1 var2       var4 var3
# 1    D    7 2018-01-03 6.50
# 2    C    5 2018-01-04 4.20
# 3    B    4 2018-01-06 4.00
# 4    A    3 2018-01-07 3.20
# 5 <NA>    2 2018-01-09 2.43
# 6 <NA>   NA 2018-01-10 2.30
# 7 <NA>   NA       <NA> 1.34
# 8 <NA>   NA       <NA> 1.20
# 9 <NA>   NA       <NA> 0.34

Тидивальный эквивалент:

library(dplyr)
library(purrr)

maxlen <- max(lengths(map(df, unique)))
df %>%
  map(~ sort(unique(.), decreasing = !inherits(., "Date"))) %>%
  .[order(lengths(.))] %>%
  map(`length<-`, maxlen) %>%                    # alternative 1
  # map(~ c(., rep(NA, maxlen - length(.)))) %>% # alternative 2
  tbl_df()

Нижняя строка, хотя: Iсогласен с @ 42- и @thelatemail, что это действительно не лучший формат для хранения.Одна из интерпретаций data.frame заключается в том, что все в строке связано.Например, в опросах каждый столбец является вопросом, а каждая строка - респондентом (лицом, проводящим опрос).При переупорядочении по-разному между столбцами эта связь полностью отбрасывается.Единственное обоснование, которое я могу придумать для , а не для более простого формата list (с @ 42-, оканчивающимся на), - для представления отчета, где я предполагаю, что вы сделаете что-то вроде

options(knitr.kable.NA="")
knitr::kable(...)
# |var1 | var2|var4       | var3|
# |:----|----:|:----------|----:|
# |D    |    7|2018-01-03 | 6.50|
# |C    |    5|2018-01-04 | 4.20|
# |B    |    4|2018-01-06 | 4.00|
# |A    |    3|2018-01-07 | 3.20|
# |     |    2|2018-01-09 | 2.43|
# |     |     |2018-01-10 | 2.30|
# |     |     |           | 1.34|
# |     |     |           | 1.20|
# |     |     |           | 0.34|
0 голосов
/ 26 октября 2018

Полагаю, можно использовать tidyverse, это кажется действительно простым с order:

df[order(df$var1, df$var2, df$var3, -as.numeric(df$var4)),]
# A tibble: 9 x 4
   var2 var1   var3 var4      
  <int> <chr> <dbl> <date>    
1     2 A      1.2  2018-01-06
2     4 A      0.34 2018-01-09
3     4 A      1.34 2018-01-03
4     7 A      3.2  2018-01-09
5     7 B      2.43 2018-01-07
6     3 C      4    2018-01-04
7     5 C      4.2  2018-01-07
8     3 D      2.3  2018-01-10
9     5 D      6.5  2018-01-10

Это эквивалент tidyverse.Требуется найти страницу справки ?arrange, которая рекомендует использовать desc() для обратного упорядочения (эквивалент использования префикса - при использовании `order):

df %>% arrange(var1, var2, var3, desc(as.numeric(var4)))
# A tibble: 9 x 4 
   var2 var1   var3 var4      
  <int> <chr> <dbl> <date>    
1     2 A      1.2  2018-01-06
2     4 A      0.34 2018-01-09
3     4 A      1.34 2018-01-03
4     7 A      3.2  2018-01-09
5     7 B      2.43 2018-01-07
6     3 C      4    2018-01-04
7     5 C      4.2  2018-01-07
8     3 D      2.3  2018-01-10
9     5 D      6.5  2018-01-10

Список будет способом возвратазначения, которые имеют неравную длину и не связаны друг с другом:

lapply(df, unique)
$var2
[1] 2 4 7 3 5

$var1
[1] "A" "B" "C" "D"

$var3
[1] 1.20 1.34 2.43 4.00 3.20 2.30 0.34 4.20 6.50

$var4
[1] "2018-01-06" "2018-01-03" "2018-01-07" "2018-01-04" "2018-01-09" "2018-01-10"
...