按因子水平的顺序对数据框中行内的值进行排序?

Sorting the values inside row in a data frame, by the order of its factor levels?

所以,我正在尝试使用 R Shiny 为桌面角色扮演游戏创建一个工具,允许玩家自动生成随机幽灵。这些统计数据是因素,顺序为“最高”、“好”、“中等”、“差”、“糟糕”和“最差”。为了创建重影,我需要将这些因素的向量取为 25 项长,随机化顺序,然后将其放入 5x5 数据框中,然后将两行从最佳到最差排序。

目前,基本的 R 代码(闪亮的东西放在一边,因为它只是使事情复杂化而且它不是这里的主要问题)看起来像这样:

arcanaVector <- c(rep("Supreme", 3),
                  rep(c("Good", "Moderate", "Poor", "Awful"), each = 5),
                  rep("Worst", 2))
arcanaLevels <- c("Supreme", "Good", "Moderate", "Poor", "Awful", "Worst")
arcanaVector <- factor(arcanaVector, ordered = TRUE, levels = arcanaLevels)
shuffled_arcana <- sample(arcanaVector)
arcana_table <- as.data.frame(matrix(shuffled_arcana,
                                     nrow = 5, ncol = 5))
row.names(arcana_table) <- c("Presence", "Manner", "Expression", "Complexity", "Tradition")

大部分代码都在工作,并且它产生的输出看起来有点像这样:

Row Names Col1 Col2 Col3 Col4 Col5
Presence Awful Good Poor Supreme Worst
Manner Good Awful Moderate Moderate Supreme
Expression Awful Poor Poor Awful Awful
Complexity Poor Good Worst Good Good
Tradition Supreme Moderate Moderate Moderate Poor

但是,无论我做什么,我似乎都无法正确排序。我试过 order(),我试过 sort(),我查看了我在 StackExchange 上看到的所有代码,但找不到任何有用的东西。充其量,它什么也没做;在最坏的情况下,它不仅无法排序,而且还剥离了因子值,因此它只显示基础数字。

例如,在状态行上排序后,它应该看起来像这样:

Row Names Col1 Col2 Col3 Col4 Col5
Presence Supreme Good Poor Awful Worst
Manner Good Awful Moderate Moderate Supreme
Expression Awful Poor Poor Awful Awful
Complexity Poor Good Worst Good Good
Tradition Supreme Moderate Moderate Moderate Poor

在您的代码中,问题出在这一行。

arcana_table <- as.data.frame(matrix(shuffled_arcana, nrow = 5, ncol = 5))

shuffled_arcana 是一个因子向量,但你不能有一个 factor-matrix,所以它将向量从因子更改为字符,因此排序不会按预期进行。

这里有一个方法 -

set.seed(2022)

arcanaVector <- c(rep("Supreme", 3),
                  rep(c("Good", "Moderate", "Poor", "Awful"), each = 5),
                  rep("Worst", 2))
arcanaLevels <- c("Supreme", "Good", "Moderate", "Poor", "Awful", "Worst")
shuffled_arcana <- sample(arcanaVector)
arcana_table <- matrix(shuffled_arcana,nrow = 5, ncol = 5)
row.names(arcana_table) <- c("Presence", "Manner", "Expression", "Complexity", "Tradition")

arcana_table <- apply(arcana_table, 1, function(x) sort(factor(x, arcanaLevels))) |>
  t() |>
  as.data.frame()

arcana_table

#                 V1       V2       V3       V4    V5
#Presence       Good     Good     Good     Good Awful
#Manner      Supreme Moderate     Poor    Awful Awful
#Expression  Supreme  Supreme Moderate Moderate  Poor
#Complexity Moderate Moderate     Poor     Poor Worst
#Tradition      Good     Poor    Awful    Awful Worst

如果您想更改特定行,您可以使用 -

arcana_table[1, ] <- as.character(sort(factor(arcana_table[1, ], arcanaLevels))) 

如果我没理解错的话,您想按选定的行对矩阵的列进行排序。如果是这样,我想你可以这样做:

chosen <- 'Presence'
arcana_table[, order(factor(arcana_table[chosen, ], levels=arcanaLevels))]
#            [,1]       [,2]       [,3]       [,4]    [,5]      
# Presence   "Supreme"  "Moderate" "Poor"     "Poor"  "Poor"    
# Manner     "Awful"    "Worst"    "Good"     "Worst" "Awful"   
# Expression "Awful"    "Poor"     "Supreme"  "Poor"  "Good"    
# Complexity "Moderate" "Awful"    "Moderate" "Good"  "Good"    
# Tradition  "Moderate" "Supreme"  "Good"     "Awful" "Moderate"

chosen <- 'Manner'
arcana_table[, order(factor(arcana_table[chosen, ], levels=arcanaLevels))]
#            [,1]       [,2]       [,3]       [,4]    [,5]   
# Presence   "Poor"     "Supreme"  "Poor"     "Poor"  "Moderate"
# Manner     "Good"     "Awful"    "Awful"    "Worst" "Worst"   
# Expression "Supreme"  "Awful"    "Good"     "Poor"  "Poor"    
# Complexity "Moderate" "Moderate" "Good"     "Good"  "Awful"   
# Tradition  "Good"     "Moderate" "Moderate" "Awful" "Supreme" 

请注意,factor 中的顺序由提供级别的顺序给出。 ordered=TRUE 论点实际上进一步区分了序数尺度和名义尺度。


数据:

arcanaVector <- structure(c(1L, 1L, 1L, 2L, 2L, 2L, 2L, 2L, 3L, 3L, 3L, 3L, 3L, 
4L, 4L, 4L, 4L, 4L, 5L, 5L, 5L, 5L, 5L, 6L, 6L), .Label = c("Supreme", 
"Good", "Moderate", "Poor", "Awful", "Worst"), class = c("ordered", 
"factor"))

set.seed(42)  ## for sake of reproducibility

arcana_table <- matrix(sample(arcanaVector), nrow=5, ncol=5,
                       dimnames=list(c("Presence", "Manner", "Expression",
                                       "Complexity", "Tradition"), NULL)) 

arcanaLevels <- c("Supreme", "Good", "Moderate", "Poor", "Awful", "Worst")