以变​​量值成为变量名并且它们的值从另一列中选取的方式重塑数据集

Reshaping dataset in a way that values for variables become variable names and their values are picked from another column

--------------------新 POST: 我过去发布了不正确的数据示例(留在下面)。实际上,我的数据在同一列下有重复的“模块”,以前的解决方案对我的问题不起作用。

我的示例数据(当前数据集):

Year <- c("2013", "2020", "2015", "2012")
Grade <- c(28, 39, 76, 54)
Code <- c("A", "B", "C", "A")
Module1 <- c("English", "English", "Science", "English")
Results1 <- c(45, 58, 34, 54)
Module2 <- c("History", "History", "History", "Art")
Results2 <- c(12, 67, 98, 45)
Module3 <- c("Art", "Geography", "Math", "Geography")
Results3 <- c(89, 84, 45, 67)
Module14 <- c("Math", "Math", "Geography", "Art")
Results14 <- c(89, 24, 95, 67)
Module15 <-c("Science", "Art", "Art", "Science")
Results15 <-c(87, 24, 25, 67)

daf <- data.frame(Id, Year, Grade, Code, Module1, Results1, Module2, Results2, Module3, Results3, Module14, Results14, Module15, Results15)

我的目标-我需要达到的数据集:

Year <- c("2013", "2020", "2015", "2012")
Grade <- c(28, 39, 76, 54)
Code <- c("A", "B", "C", "A")
English <- c(45, 58,NA,54)
Math <- c(89, 24,45, NA)
Science <- c(87, NA, 34, 67)
Geography <- c(NA, 84, 95,67)
Art <- c(89,24,25,45)

wished_df <- data.frame(Id, Year, Grade, Code, English, Math, Science,Geography, Art)

再次感谢您的帮助!

-------------------------------- 老 POST: 我正在尝试将我当前的数据重塑为新格式。

Module1 <- c("English", "Math", "Science", "Geography")
Results1 <- c(45, 58, 34, 54)
Module2 <- c("Math", "History", "English", "Art")
Results2 <- c(12, 67, 98, 45)
Module3 <- c("History", "Art", "English", "Geography")
Results3 <- c(89, 84, 45, 67)

daf <- data.frame(Module1, Results1, Module2, Results2, Module3, Results3)

我需要的是将模块名称设置为“变量名称”,并将模块结果设置为“变量名称的值”,如下所示:

English1 <- c(45, 98, 45)
Math1 <- c(58, 12, NA)
Science1 <- c(34, NA, NA)
Geography1 <- c(54,NA, 67)
Art1 <- c(NA, 45, 84)

wished_df <- data.frame(English1, Math1, Science1,Geography1, Art1)

感谢您的任何想法。

1) reshape 使用最后注释中的数据,将输入列名称分成两组(模块列和结果列),给出 varying。使用该 reshape 到长格式,其中 varying= 定义输入中的哪些列对应于长格式中的单个列。 v.names= 指定用于从不同列生成的两列中的每一列的名称。 reshape 将给出一个包含时间列、模块列、结果列和 ID 列的数据框。我们不需要 id 列,所以使用 [-4].

删除它

然后将其重塑回新的宽幅形式。 idvar= 指定输出行的来源,timevar= 指定输出列的来源。其他一切都是结果的主体。 reshape 将生成一个我们不需要的时间列,因此使用 [-1] 将其删除。最后我们删除了每个列名的垃圾部分。

没有使用包。

varying <- split(names(daf), sub("\d+$", "", names(daf)))
long <- reshape(daf, dir = "long", varying = varying, v.names = names(varying))[-4]
wide <- reshape(long, dir = "wide", idvar = "time", timevar = "Module")[-1]
names(wide) <- sub(".*[.]", "", names(wide))  

给予:

> wide
    English Math Science Geography History Art
1.1      45   58      34        54      NA  NA
1.2      98   12      NA        NA      67  45
1.3      45   NA      NA        67      89  84

2)pivot_使用末尾Note中的数据,指定使用所有列,使用.names指定long中的列名形式取自输入的列名的第一部分,其中输入的名称根据 names_pattern= 正则表达式拆分。然后转到一个新的宽格式,其中列名取自“模块”列,结果正文中的值取自“结果”列。索引列将定义行,之后可以省略。

library(dplyr)
library(tidyr)

daf %>%
  pivot_longer(everything(), names_to = c(".value", "index"), 
    names_pattern = "(\D+)(\d+)") %>%
  pivot_wider(names_from = Module, values_from = Results) %>%
  select(-index)

给予:

# A tibble: 3 x 6
  English  Math History   Art Science Geography
    <dbl> <dbl>   <dbl> <dbl>   <dbl>     <dbl>
1      45    58      NA    NA      34        54
2      98    12      67    45      NA        NA
3      45    NA      89    84      NA        67

3) unlist/tapply UUsing the data in the end of the Note, another base solution can be fashed by 单独取消列出模块和结果列以获得长形式并使用 tapply 转换为宽形式。没有使用包

is_mod <- grepl("Module", names(daf))
long <- data.frame(Module = unlist(daf[is_mod]), Results = unlist(daf[!is_mod]))
tab <- tapply(long$Results, list(sub("\d+$", "", rownames(long)), long$Module), sum)
as.data.frame.matrix(tab)

给予:

        Art English Geography History Math Science
Module1  NA      45        54      NA   58      34
Module2  45      98        NA      67   12      NA
Module3  84      45        67      89   NA      NA

备注

Module1 <- c("English", "Math", "Science", "Geography")
Results1 <- c(45, 58, 34, 54)
Module2 <- c("Math", "History", "English", "Art")
Results2 <- c(12, 67, 98, 45)
Module3 <- c("History", "Art", "English", "Geography")
Results3 <- c(89, 84, 45, 67)
daf <- data.frame(Module1, Results1, Module2, Results2, Module3, Results3)

A data.table版本:

library(data.table)
library(magrittr)
dt <- as.data.table(daf)
dt %>%
  melt.data.table(measure.vars = patterns("^Module", "^Result")) %>%
  dcast.data.table(variable ~ ..., value.var = "value2")

给予:

Key: <variable>
   variable   Art English Geography History  Math Science
     <fctr> <num>   <num>     <num>   <num> <num>   <num>
1:        1    NA      45        54      NA    58      34
2:        2    45      98        NA      67    12      NA
3:        3    84      45        67      89    NA      NA