在BASE R中操作data.frame格式
我已经看到了给出的答案,但我想知道在我的情况下,是否有一种有效的方法可以在BASE R中将我的在BASE R中操作data.frame格式,r,dataframe,R,Dataframe,我已经看到了给出的答案,但我想知道在我的情况下,是否有一种有效的方法可以在BASE R中将我的输入data.frame更改为下面所示的所需输出data.frame input <- data.frame(id = c(1,3,6), school = LETTERS[1:3], read_1 = c(20,22,24), read_1_sp = c(T,F,T), read_2 =c(45,47,49),read_2_sp = c(F,F,F),
输入
data.frame更改为下面所示的所需输出
data.frame
input <- data.frame(id = c(1,3,6), school = LETTERS[1:3], read_1 = c(20,22,24),
read_1_sp = c(T,F,T), read_2 =c(45,47,49),read_2_sp = c(F,F,F),
math_1 =c(20,22,NA), math_1_sp = c(T,F,NA), math_2 = c(NA,35,37),
math_2_sp =c(NA,F,F))
output <- data.frame(id = c(rep(1,3),rep(3,4), rep(6, 3)),school = c(rep("A",3),rep("B",4), rep("C", 3)),
subject = c("read","read","math","read","read","math", "math","read","read","math"),
no.= c(1,2,1,1,2,1,2,1,2,2), score = c(20,45,20,22,47,22,35,24,49,37),
sp = c(T,F,T,T,F,T,T,T,F,T))
input1)基本-重塑创建两个元素的列表,变化
,每个元素都是名称的字符向量——第一个元素是分数
名称的向量,第二个元素是sp
名称的向量。将其与基础一起使用重塑。然后按idvar
变量排序(如果不需要,则省略执行排序的两行),并使用na删除带有NAs的行。省略
<代码>重塑
生成一个主题
列,其中包含read_1
等条目。transform语句将其拆分为两列,subject
和no
varying <- lapply(c("\\d$", "sp$"), grep, names(input), value = TRUE)
r <- reshape(input, dir = "long", idvar = c("id", "school"),
varying = varying, v.names = c("score", "sp"),
times = varying[[1]], timevar = "subject")
o <- with(r, order(id, school))
r <- r[o, ]
r <- na.omit(r)
transform(r, subject = sub("_.*", "", subject), no = as.numeric(sub(".*_", "", subject)))
2)data.table-melt问题要求基本解决方案,但为了进行比较,我们还在data.table中显示了使用melt
的解决方案
将input
转换为data.table,并使用键和指示的模式将其熔化melt
与REFORMATE
中的时间=
没有对应项,而是在变量.name
列中提供索引号,在本例中,该列为主题。我们使用它来索引时间
。这会产生诸如read_1
之类的元素,因此我们使用fread
将subject
分为两列,subject
和no
。最后,使用na删除具有NAs的行。省略并通过指定键进行排序
library(data.table)
input2 <- as.data.table(input, key = c("id", "school"))
times <- grep("\\d$", names(input2), value = TRUE) # score col names
melt(input2, measure = patterns(sp = "sp", score = "\\d$"), variable.name = "subject")[,
c("subject", "no"):= fread(text = times[subject], sep = "_")][,
na.omit(.SD), key = key(input2)]
1)基本-重塑创建两个元素的列表,每个元素都是名称的字符向量,第一个元素是分数
名称的向量,第二个元素是sp
名称的向量。将其与基础一起使用重塑。然后按idvar
变量排序(如果不需要,则省略执行排序的两行),并使用na删除带有NAs的行。省略
<代码>重塑
生成一个主题
列,其中包含read_1
等条目。transform语句将其拆分为两列,subject
和no
varying <- lapply(c("\\d$", "sp$"), grep, names(input), value = TRUE)
r <- reshape(input, dir = "long", idvar = c("id", "school"),
varying = varying, v.names = c("score", "sp"),
times = varying[[1]], timevar = "subject")
o <- with(r, order(id, school))
r <- r[o, ]
r <- na.omit(r)
transform(r, subject = sub("_.*", "", subject), no = as.numeric(sub(".*_", "", subject)))
2)data.table-melt问题要求基本解决方案,但为了进行比较,我们还在data.table中显示了使用melt
的解决方案
将input
转换为data.table,并使用键和指示的模式将其熔化melt
与REFORMATE
中的时间=
没有对应项,而是在变量.name
列中提供索引号,在本例中,该列为主题。我们使用它来索引时间
。这会产生诸如read_1
之类的元素,因此我们使用fread
将subject
分为两列,subject
和no
。最后,使用na删除具有NAs的行。省略并通过指定键进行排序
library(data.table)
input2 <- as.data.table(input, key = c("id", "school"))
times <- grep("\\d$", names(input2), value = TRUE) # score col names
melt(input2, measure = patterns(sp = "sp", score = "\\d$"), variable.name = "subject")[,
c("subject", "no"):= fread(text = times[subject], sep = "_")][,
na.omit(.SD), key = key(input2)]
在tidyverse
中,我们可以
library(tidyr)
library(stringr)
input %>%
rename_at(vars(matches('\\d+$')), ~ str_c(., '_score')) %>%
pivot_longer(cols = -c(id, school), names_to = c('subject', 'no', '.value'),
names_sep="_", values_drop_na = TRUE)
# A tibble: 10 x 6
# id school subject no score sp
# <dbl> <fct> <chr> <chr> <dbl> <lgl>
# 1 1 A read 1 20 TRUE
# 2 1 A read 2 45 FALSE
# 3 1 A math 1 20 TRUE
# 4 3 B read 1 22 FALSE
# 5 3 B read 2 47 FALSE
# 6 3 B math 1 22 FALSE
# 7 3 B math 2 35 FALSE
# 8 6 C read 1 24 TRUE
# 9 6 C read 2 49 FALSE
#10 6 C math 2 37 FALSE
在tidyverse
中,我们可以
library(tidyr)
library(stringr)
input %>%
rename_at(vars(matches('\\d+$')), ~ str_c(., '_score')) %>%
pivot_longer(cols = -c(id, school), names_to = c('subject', 'no', '.value'),
names_sep="_", values_drop_na = TRUE)
# A tibble: 10 x 6
# id school subject no score sp
# <dbl> <fct> <chr> <chr> <dbl> <lgl>
# 1 1 A read 1 20 TRUE
# 2 1 A read 2 45 FALSE
# 3 1 A math 1 20 TRUE
# 4 3 B read 1 22 FALSE
# 5 3 B read 2 47 FALSE
# 6 3 B math 1 22 FALSE
# 7 3 B math 2 35 FALSE
# 8 6 C read 1 24 TRUE
# 9 6 C read 2 49 FALSE
#10 6 C math 2 37 FALSE
您是否尝试过stats::重塑?这不是最直观的处理方法,但它可以实现您所寻求的重塑。由于您试图缩小几个列,我怀疑将需要几个独立的调用来重塑
,然后合并
它们。在我看来,这是tidyr::pivot\u longer
的强大动力。。。虽然我很欣赏你坚持使用base R的动机,但便利功能之所以如此重要是有原因的。。。便利性:-)您是否考虑过sqldf
或其他基于sql的解决方案?这与您的base-R约束相反,但是如果您已经在工作流的其他地方使用了sqldf
、DBI
、RSQLite
,或者其他一些DBMS,您可以利用它。您是否尝试过stats::restrape
?这不是最直观的处理方法,但它可以实现您所寻求的重塑。由于您试图缩小几个列,我怀疑将需要几个独立的调用来重塑
,然后合并
它们。在我看来,这是tidyr::pivot\u longer
的强大动力。。。虽然我很欣赏你坚持使用base R的动机,但便利功能之所以如此重要是有原因的。。。便利性:-)您是否考虑过sqldf
或其他基于sql的解决方案?这与您的base-R约束相反,但是如果您已经使用了sqldf
、DBI
、RSQLite
,或者工作流中的其他一些DBMS,您可以利用它。@rnorouzian我添加了一个base R
。@rnorouzian我删除了该解决方案,因为它可以收集一些dvs。不管怎样,你有另一个解决方案,是在基地工作R@Reza我将重塑更改为拆分,因为已经有一个解决方案。@rnorouzian我添加了一个base R
@rnorouzian我删除了该解决方案,因为它可以收集一些DV。不管怎样,你有另一个解决方案,是在基地工作R@Reza我将重塑更改为拆分,因为已经有解决方案。稍微简化(1)并添加(2)。稍微简化(1)并添加(2)。