使用 dcast 时,如何根据列“Col”指定列顺序?
df <- dcast(x, ID ~ ColumnName, value.var = "Answer")
Run Code Online (Sandbox Code Playgroud)
我需要解决方案不特定于数据,因为 x 可以是任何问题的结果(因此 Col 可以是 1-3 或 1-2 等)。下面是 x 的两个虚拟示例。
ID Answer ColumnName Col
1 Anduin First Name 1
1 Wrynn Surname 2
1 Alliance Faction 3
2 Sylvanas First Name 1
2 Windrunner Surname 2
2 Horde Faction 3
ID Answer ColumnName Col
1 The Kirin Tor Quest 1
1 90 Level 2
2 Emissary Quest 1
2 38 Level 2
Run Code Online (Sandbox Code Playgroud)
它没有得到很好的记录,既不是 inhelp("dcast", "reshape2")也不是 inhelp("dcast", "data.table")但列是按因子级别排序的,如果ColumnName是一个因子。
factor()列按字母顺序排列,这不符合中指定的顺序 Col
reshape2::dcast(x, ID ~ ColumnName, value.var = "Answer")
Run Code Online (Sandbox Code Playgroud)
Run Code Online (Sandbox Code Playgroud)ID Faction First Name Surname 1 1 Alliance Anduin Wrynn 2 2 Horde Sylvanas Windrunner
显然,OP正在按照出现的顺序Col编号ColumnName。因此,Col是多余的,可以忽略。
有几种方法可以直接在 的公式中创建按外观排序的因子水平dcast():
reshape2::dcast(x1, ID ~ factor(ColumnName, levels = unique(ColumnName)), value.var = "Answer")
Run Code Online (Sandbox Code Playgroud)
Run Code Online (Sandbox Code Playgroud)ID First Name Surname Faction 1 1 Anduin Wrynn Alliance 2 2 Sylvanas Windrunner Horde
reshape2::dcast(x2, ID ~ factor(ColumnName, levels = unique(ColumnName)), value.var = "Answer")
Run Code Online (Sandbox Code Playgroud)
Run Code Online (Sandbox Code Playgroud)ID Quest Level 1 1 The Kirin Tor 90 2 2 Emissary 38
根据 OP 的要求,该解决方案并非特定于数据。
forcats该forcats包有一些方便的功能来处理因素。as_factor()按照它们出现的顺序创建级别:
reshape2::dcast(x1, ID ~ forcats::as_factor(ColumnName), value.var = "Answer")
Run Code Online (Sandbox Code Playgroud)
(结果和上面一样。)
为了使代码更明确,fct_inorder()可以使用:
reshape2::dcast(x1, ID ~ forcats::fct_inorder(ColumnName), value.var = "Answer")
Run Code Online (Sandbox Code Playgroud)
Col如果请求的列顺序与出现顺序不同,则可以按从 派生的因子水平对列进行排序Col。为了演示,使用了修改后的示例数据集。
以 R 为基数,
reshape2::dcast(x3, ID ~ reorder(factor(ColumnName), Col), value.var = "Answer")
Run Code Online (Sandbox Code Playgroud)
Run Code Online (Sandbox Code Playgroud)ID Surname Faction First Name 1 1 Wrynn Alliance Anduin 2 2 Windrunner Horde Sylvanas
或与 forcats
reshape2::dcast(x3, ID ~ forcats::fct_reorder(ColumnName, Col), value.var = "Answer")
Run Code Online (Sandbox Code Playgroud)
x1 <- readr::read_table(
"ID Answer ColumnName Col
1 Anduin First Name 1
1 Wrynn Surname 2
1 Alliance Faction 3
2 Sylvanas First Name 1
2 Windrunner Surname 2
2 Horde Faction 3")
x2 <- data.table::fread(
'ID Answer ColumnName Col
1 "The Kirin Tor" Quest 1
1 90 Level 2
2 Emissary Quest 1
2 38 Level 2')
Run Code Online (Sandbox Code Playgroud)
具有给定列顺序的修改样本数据集(出现顺序或字母顺序除外):
x3 <- readr::read_table(
"ID Answer ColumnName Col
1 Anduin First Name 3
1 Wrynn Surname 1
1 Alliance Faction 2
2 Sylvanas First Name 3
2 Windrunner Surname 1
2 Horde Faction 2")
Run Code Online (Sandbox Code Playgroud)
我没有看到dcast允许指定列的最终顺序的参数,但始终可以对结果进行子集化。
fun_dcast <- function(DF, formula = ID ~ ColumnName, value.var = "Answer"){
reshape2::dcast(DF, formula, value.var = value.var)[c(1, 1 + unique(DF[["Col"]]))]
}
fun_dcast(x1)
# ID Faction First Name Surname
#1 1 Alliance Anduin Wrynn
#2 2 Horde Sylvanas Windrunner
fun_dcast(x2)
# ID Level Quest
#1 1 90 The Kirin Tor
#2 2 38 Emissary
Run Code Online (Sandbox Code Playgroud)
数据。
x1 <- read.table(text = "
ID Answer ColumnName Col
1 Anduin 'First Name' 1
1 Wrynn Surname 2
1 Alliance Faction 3
2 Sylvanas 'First Name' 1
2 Windrunner Surname 2
2 Horde Faction 3
", header = TRUE)
x2 <- read.table(text = "
ID Answer ColumnName Col
1 'The Kirin Tor' Quest 1
1 90 Level 2
2 Emissary Quest 1
2 38 Level 2
", header = TRUE)
Run Code Online (Sandbox Code Playgroud)