如何使用两个规则从一个变量创建新变量

how to create new variables from one variable using two rules

对于从一个变量创建新变量的任何帮助,我将不胜感激。

具体来说,我需要帮助同时为每个 IDE 的各个列创建一行,其中 E 的每个新列,(即 E1E2E3) 包含 ID 的每一行的 E 的值。我尝试这样做 melt 后跟 spread 但我收到错误消息:

Error: Duplicate identifiers for rows (4, 7, 9), (1, 3, 6), (2, 5, 8)

此外,我尝试了讨论的解决方案 and 但这些对我的情况不起作用,因为我需要能够为行 (4, 1, 2), (7 , 3, 5), 和 (9, 6, 8)。即,第 (4, 1, 2) 行的 E 应命名为 E1,第 (7, 3, 5) 行的 E 应命名为 E2E 行 (9, 6, 8) 应命名为 E3,依此类推。

#data

dT<-structure(list(A = c("a1", "a2", "a1", "a1", "a2", "a1", "a1", 
    "a2", "a1"), B = c("b2", "b2", "b2", "b1", "b2", "b2", "b1", 
    "b2", "b1"), ID = c("3", "4", "3", "1", "4", "3", "1", "4", "1"
    ), E = c(0.621142094943352, 0.742109450696123, 0.39439152996948, 
    0.40694392882818, 0.779607277916503, 0.550579323666347, 0.352622183880119, 
    0.690660491345867, 0.23378944873769)), class = c("data.table", 
    "data.frame"), row.names = c(NA, -9L))

#我的尝试

    A  B ID         E
1: a1 b2  3 0.6211421
2: a2 b2  4 0.7421095
3: a1 b2  3 0.3943915
4: a1 b1  1 0.4069439
5: a2 b2  4 0.7796073
6: a1 b2  3 0.5505793
7: a1 b1  1 0.3526222
8: a2 b2  4 0.6906605
9: a1 b1  1 0.2337894

aTempDF <- melt(dT, id.vars = c("A", "B", "ID")) )

    A  B  ID variable    value
1: a1 b2  3        E 0.6211421
2: a2 b2  4        E 0.7421095
3: a1 b2  3        E 0.3943915
4: a1 b1  1        E 0.4069439
5: a2 b2  4        E 0.7796073
6: a1 b2  3        E 0.5505793
7: a1 b1  1        E 0.3526222
8: a2 b2  4        E 0.6906605
9: a1 b1  1        E 0.2337894

aTempDF%>%spread(variable, value)

Error: Duplicate identifiers for rows (4, 7, 9), (1, 3, 6), (2, 5, 8)

#预期输出

    A  B  ID       E1           E2           E3
1: a1 b2  3        0.6211421    0.3943915    0.5505793
2: a2 b2  4        0.7421095    0.7796073    0.6906605 
3: a1 b1  1        0.4069439    0.3526222    0.2337894

在此先感谢您的帮助。

您可以使用 dcast 来自 data.table

library(data.table)
dcast(dT, A + B + ID ~ paste0("E", rowid(ID)))
#   A  B ID        E1        E2        E3
#1 a1 b1  1 0.4069439 0.3526222 0.2337894
#2 a1 b2  3 0.6211421 0.3943915 0.5505793
#3 a2 b2  4 0.7421095 0.7796073 0.6906605

您需要先创建正确的 'time variable',这正是 rowid(ID) 所做的。

对于那些寻找 tidyverse 解决方案的人:

library(tidyverse)

dT <- structure(
  list(
    A = c("a1", "a2", "a1", "a1", "a2", "a1", "a1", "a2", "a1"),
    B = c("b2", "b2", "b2", "b1", "b2", "b2", "b1", "b2", "b1"),
    ID = c("3", "4", "3", "1", "4", "3", "1", "4", "1"),
    E = c(0.621142094943352, 0.742109450696123, 0.39439152996948, 0.40694392882818,
          0.550579323666347, 0.352622183880119, 0.690660491345867, 0.23378944873769,
          0.779607277916503)),
  class = c("data.table", 
            "data.frame"),
  row.names = c(NA, -9L))
dT %>% 
  as_tibble() %>%  # since dataset is a data.table object
  group_by(A, B, ID) %>% 
  # Just so columns are "E1", "E2", etc.
  mutate(rn = glue::glue("E{row_number()}")) %>% 
  ungroup() %>% 
  spread(rn, E) %>%
  # not necessary, just making output in the same order as your expected output
  arrange(desc(B)) 
# A tibble: 3 x 6
#  A     B     ID       E1    E2    E3
#  <chr> <chr> <chr> <dbl> <dbl> <dbl>
#1 a1    b2    3     0.621 0.394 0.551
#2 a2    b2    4     0.742 0.780 0.691
#3 a1    b1    1     0.407 0.353 0.234

如已接受的答案中所述,您首先需要一个“关键”变量来传播。这是使用 row_number()glue 创建的,其中 glue 只是为您提供正确的 E1、E2 等变量名称。

group_by 部分只是确保行号与 A、B 和 ID 有关。


编辑 tidyr >= 1.0.0

(不那么)新的 pivot_ 函数取代了 gatherspread 并且消除了 glue 新变量名称在 mutate 中的需要。

dT %>% 
  as_tibble() %>%  # since dataset is a data.table object
  group_by(A, B, ID) %>% 
  # no longer need to glue (or paste) the names together but still need a row number
  mutate(rn = row_number()) %>% 
  ungroup() %>% 
  pivot_wider(names_from = rn, values_from = E, names_glue = "E{.name}") %>% # names_glue argument allows for easy transforming of the new variable names
  # not necessary, just making output in the same order as your expected output
  arrange(desc(B)) 
# A tibble: 3 x 6
#  A     B     ID       E1    E2    E3
#  <chr> <chr> <chr> <dbl> <dbl> <dbl>
#1 a1    b2    3     0.621 0.394 0.551
#2 a2    b2    4     0.742 0.780 0.691
#3 a1    b1    1     0.407 0.353 0.234