[英]Change a level of a factor after another level
我想改變一個因素的水平順序,以便一個特定的水平緊跟在另一個水平之后,但我正在努力如何有效地做到這一點。
假設我們想改變以下因子的水平,使“20”緊跟在“10”之后。 所以我嘗試了這個並成功地得到了預期的結果:
library(tidyverse)
sample_factor <- factor(1:30)
trial_factor1 <- sample_factor %>% fct_relevel("20", after=which(levels(.)=="10"))
levels(trial_factor1)
#> [1] "1" "2" "3" "4" "5" "6" "7" "8" "9" "10" "20" "11" "12" "13" "14"
#> [16] "15" "16" "17" "18" "19" "21" "22" "23" "24" "25" "26" "27" "28" "29" "30"
但是,如果將初始因子的順序顛倒,則不起作用:
trial_factor2 <- sample_factor %>% fct_rev() %>% fct_relevel("20", after=which(levels(.)=="10"))
levels(trial_factor2)
#> [1] "30" "29" "28" "27" "26" "25" "24" "23" "22" "21" "19" "18" "17" "16" "15"
#> [16] "14" "13" "12" "11" "10" "9" "20" "8" "7" "6" "5" "4" "3" "2" "1"
這可能是因為在這種情況下,“20”最初位於“10”之前。
此外,如果我還嘗試更改順序,使“30”緊隨“20”之后(預期因子水平:...、10、20、30、...),結果會變得更糟:
trial_factor3 <- sample_factor %>% fct_rev() %>% fct_relevel("20", after=which(levels(.)=="10")) %>%
fct_relevel("30", after=which(levels(.)=="20"))
levels(trial_factor3)
#> [1] "29" "28" "27" "26" "25" "24" "23" "22" "21" "19" "18" "17" "16" "15" "14"
#> [16] "13" "12" "11" "10" "9" "20" "8" "30" "7" "6" "5" "4" "3" "2" "1"
由reprex package (v2.0.1) 於 2022 年 8 月 18 日創建
在我的實際情況下,我想多次(超過5次)改變水平的順序,我並不清楚因素水平的初始順序,所以我發現靈活改變順序真的很困難。
非常感謝您提前提供的幫助!
問題是after
參數指定 position 將級別放置在最終output 中,而使用after = which(levels(.) == "10")
您正在根據當前Z4757FE07FD492A8BEDEEZA6 的目標確定after
. 因此,如果您從訂單的前面刪除它,那么您對目標位置的描述需要相應地調整。 如果它是從目的地之后的某個地方移動的,那很好。 因此,對於您的應用程序,我認為您需要測試您有哪些情況。 這是一個小幫手 function 來測試並返回適當定位的重新調平。
注意:如果您要一次移動多個級別,則必須使 function 更加復雜,以測試從目的地之前有多少級別並相應地進行調整。
library(tidyverse)
f <- factor(1:5)
# works because nothing is removed from before the "after" position
f %>% fct_relevel("5", after = which(levels(.) == "3")) %>% levels()
#> [1] "1" "2" "3" "5" "4"
# fails because you are removing one element from before the "after" position
# so the new location should be shifted by 1
f %>% fct_relevel("3", after = which(levels(.) == "4")) %>% levels()
#> [1] "1" "2" "4" "5" "3"
# this function tests if the moves comes from before or after destination
fct_relevel_after <- function(fct, lev, after){
l <- levels(fct)
a <- match(lev, l)
b <- match(after, l)
if(a < b) {
return(fct_relevel(fct, lev, after = b-1))
} else {
return(fct_relevel(fct, lev, after = b))
}
}
# both work as desired
f %>% fct_relevel_after("5", "3") %>% levels()
#> [1] "1" "2" "3" "5" "4"
f %>% fct_relevel_after("3", "4") %>% levels()
#> [1] "1" "2" "4" "3" "5"
由代表 package (v2.0.1) 於 2022 年 8 月 17 日創建
似乎fct_relevel
旨在按位置工作,將此級別設為第 n 級(其中n = after + 1
... 有點奇怪的設計/命名決定),但您只想根據級別名稱(標簽)工作。
我們可以編寫自己的版本來執行此操作,將label轉換為position ,並解決標簽前后的問題。 (另外,為什么在一個樣本中使用 30 個級別,而 5 個級別會很好呢?)
fct_relevel_label = function(.f, level, after_label) {
lev = levels(.f)
move = which(lev == level)
target = which(lev == after_label)
after = if(move <= target) {target - 1} else {target}
fct_relevel(.f, level, after = after)
}
factor(1:5) %>% fct_relevel_label("2", after_label = "4") %>% levels
# [1] "1" "3" "4" "2" "5"
factor(1:5) %>% fct_rev() %>% fct_relevel_label("2", after_label = "4") %>% levels
# [1] "5" "4" "2" "3" "1"
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.