/tests/testthat/test-verb-pivot-wider.R

https://github.com/hadley/dbplyr · R · 212 lines · 165 code · 40 blank · 7 comment · 0 complexity · 430b7535db84bc3ff4997d17a7dd0d0d MD5 · raw file

  1. spec <- tibble(
  2. .name = c("x", "y"),
  3. .value = "val",
  4. key = c("x", "y")
  5. )
  6. spec1 <- tibble(.name = "x", .value = "val", key = "x")
  7. test_that("can pivot all cols to wide", {
  8. expect_equal(
  9. memdb_frame(key = c("x", "y", "z"), val = 1:3) %>%
  10. tidyr::pivot_wider(names_from = key, values_from = val) %>%
  11. collect(),
  12. tibble(x = 1, y = 2, z = 3)
  13. )
  14. spec <- tibble(
  15. .name = c("x", "y", "z"),
  16. .value = "val",
  17. key = c("x", "y", "z")
  18. )
  19. expect_snapshot(
  20. lazy_frame(key = c("x", "y", "z"), val = 1:3) %>%
  21. dbplyr_pivot_wider_spec(spec)
  22. )
  23. })
  24. test_that("non-pivoted cols are preserved", {
  25. df <- lazy_frame(a = 1, key = c("x", "y"), val = 1:2)
  26. expect_equal(
  27. dbplyr_pivot_wider_spec(df, spec) %>% op_vars(),
  28. c("a", "x", "y")
  29. )
  30. })
  31. test_that("implicit missings turn into explicit missings", {
  32. df <- memdb_frame(a = 1:2, key = c("x", "y"), val = 1:2)
  33. expect_equal(
  34. memdb_frame(a = 1:2, key = c("x", "y"), val = 1:2) %>%
  35. tidyr::pivot_wider(names_from = key, values_from = val) %>%
  36. collect(),
  37. tibble(a = 1:2, x = c(1, NA), y = c(NA, 2))
  38. )
  39. expect_snapshot(
  40. lazy_frame(a = 1:2, key = c("x", "y"), val = 1:2) %>%
  41. dbplyr_pivot_wider_spec(spec)
  42. )
  43. })
  44. test_that("error when overwriting existing column", {
  45. df <- memdb_frame(
  46. a = c(1, 1),
  47. key = c("a", "b"),
  48. val = c(1, 2)
  49. )
  50. expect_snapshot_error(
  51. tidyr::pivot_wider(df, names_from = key, values_from = val)
  52. )
  53. })
  54. test_that("grouping is preserved", {
  55. df <- lazy_frame(a = 1, key = "x", val = 2)
  56. expect_equal(
  57. df %>%
  58. dplyr::group_by(a) %>%
  59. dbplyr_pivot_wider_spec(spec1) %>%
  60. group_vars(),
  61. "a"
  62. )
  63. })
  64. # https://github.com/tidyverse/tidyr/issues/804
  65. test_that("column with `...j` name can be used as `names_from`", {
  66. df <- memdb_frame(...8 = c("x", "y", "z"), val = 1:3)
  67. pv <- tidyr::pivot_wider(df, names_from = ...8, values_from = val) %>% collect()
  68. expect_named(pv, c("x", "y", "z"))
  69. })
  70. # column names -------------------------------------------------------------
  71. test_that("dbplyr_build_wider_spec can handle multiple columns", {
  72. df <- memdb_frame(
  73. x = c("X", "Y"),
  74. y = 1:2,
  75. a = 1:2,
  76. b = 1:2
  77. )
  78. expect_equal(
  79. dbplyr_build_wider_spec(df, x:y, a:b),
  80. tibble::tribble(
  81. ~.name, ~.value, ~x, ~y,
  82. "a_X_1", "a", "X", 1L,
  83. "a_Y_2", "a", "Y", 2L,
  84. "b_X_1", "b", "X", 1L,
  85. "b_Y_2", "b", "Y", 2L
  86. )
  87. )
  88. })
  89. # keys ---------------------------------------------------------
  90. test_that("can override default keys", {
  91. df <- tibble::tribble(
  92. ~row, ~name, ~var, ~value,
  93. 1, "Sam", "age", 10,
  94. 2, "Sam", "height", 1.5,
  95. 3, "Bob", "age", 20,
  96. )
  97. df_db <- memdb_frame(!!!df)
  98. expect_equal(
  99. df_db %>%
  100. tidyr::pivot_wider(id_cols = name, names_from = var, values_from = value) %>%
  101. collect(),
  102. tibble::tribble(
  103. ~name, ~age, ~height,
  104. "Bob", 20, NA,
  105. "Sam", 10, 1.5
  106. )
  107. )
  108. })
  109. # non-unqiue keys ---------------------------------------------------------
  110. test_that("values_fn can be a single function", {
  111. df <- lazy_frame(a = c(1, 1, 2), key = c("x", "x", "x"), val = c(1, 10, 100))
  112. expect_snapshot(dbplyr_pivot_wider_spec(df, spec1, values_fn = sum))
  113. })
  114. test_that("values_fn cannot be NULL", {
  115. df <- lazy_frame(a = 1, key = "x", val = 1)
  116. expect_snapshot_error(dbplyr_pivot_wider_spec(df, spec1, values_fn = NULL))
  117. })
  118. # can fill missing cells --------------------------------------------------
  119. test_that("can fill in missing cells", {
  120. df <- memdb_frame(g = c(1, 2), name = c("x", "y"), value = c(1, 2))
  121. df_lazy <- lazy_frame(g = c(1, 2), name = c("x", "y"), value = c(1, 2))
  122. expect_equal(tidyr::pivot_wider(df) %>% pull(x), c(1, NA))
  123. expect_equal(tidyr::pivot_wider(df, values_fill = 0) %>% pull(x), c(1, 0))
  124. expect_snapshot(dbplyr_pivot_wider_spec(df_lazy, spec, values_fill = 0))
  125. expect_equal(
  126. tidyr::pivot_wider(df, values_fill = list(value = 0)) %>%
  127. pull(x),
  128. c(1, 0)
  129. )
  130. expect_snapshot(
  131. dbplyr_pivot_wider_spec(
  132. df_lazy,
  133. spec,
  134. values_fill = list(value = 0)
  135. )
  136. )
  137. })
  138. test_that("values_fill only affects missing cells", {
  139. df <- memdb_frame(g = c(1, 2), name = c("x", "y"), value = c(1, NA))
  140. out <- tidyr::pivot_wider(df, values_fill = 0) %>%
  141. collect()
  142. expect_equal(out$y, c(0, NA))
  143. })
  144. # multiple values ----------------------------------------------------------
  145. test_that("can pivot from multiple measure cols", {
  146. df <- memdb_frame(row = 1, var = c("x", "y"), a = 1:2, b = 3:4)
  147. pv <- tidyr::pivot_wider(df, names_from = var, values_from = c(a, b)) %>%
  148. collect()
  149. expect_named(pv, c("row", "a_x", "a_y", "b_x", "b_y"))
  150. expect_equal(pv$a_x, 1)
  151. expect_equal(pv$b_y, 4)
  152. })
  153. test_that("column order in output matches spec", {
  154. df <- tibble::tribble(
  155. ~hw, ~name, ~mark, ~pr,
  156. "hw1", "anna", 95, "ok",
  157. "hw2", "anna", 70, "meh",
  158. )
  159. # deliberately create weird order
  160. sp <- tibble::tribble(
  161. ~hw, ~.value, ~.name,
  162. "hw1", "mark", "hw1_mark",
  163. "hw1", "pr", "hw1_pr",
  164. "hw2", "pr", "hw2_pr",
  165. "hw2", "mark", "hw2_mark",
  166. )
  167. pv <- dbplyr_pivot_wider_spec(lazy_frame(!!!df), sp)
  168. expect_equal(pv %>% op_vars(), c("name", sp$.name))
  169. })
  170. test_that("cannot pivot lazy frames", {
  171. expect_snapshot_error(tidyr::pivot_wider(lazy_frame(name = "x", value = 1)))
  172. })