2010-03-03 67 views
93

我有一些數值變量和一些分類factor變量。這些因素的級別順序並不是我希望它們成爲的方式。在不改變值順序的情況下重新排序一個因子的水平

numbers <- 1:4 
letters <- factor(c("a", "b", "c", "d")) 
df <- data.frame(numbers, letters) 
df 
# numbers letters 
# 1  1  a 
# 2  2  b 
# 3  3  c 
# 4  4  d 

如果我改變級別的順序,字母不再與它們對應的號碼(我的數據是從這個角度上總廢話)。

levels(df$letters) <- c("d", "c", "b", "a") 
df 
# numbers letters 
# 1  1  d 
# 2  2  c 
# 3  3  b 
# 4  4  a 

我只是想改變水平順序,因此打印時,該酒吧在期望的順序顯示 - 這可以從默認的字母順序不同。

回答

102

使用levels說法factor

df <- data.frame(f = 1:4, g = letters[1:4]) 
df 
# f g 
# 1 1 a 
# 2 2 b 
# 3 3 c 
# 4 4 d 

levels(df$g) 
# [1] "a" "b" "c" "d" 

df$g <- factor(df$g, levels = letters[4:1]) 
# levels(df$g) 
# [1] "d" "c" "b" "a" 

df 
# f g 
# 1 1 a 
# 2 2 b 
# 3 3 c 
# 4 4 d 
+1

謝謝,這工作。由於一些奇怪的原因,ggplot現在正確地改變了圖例中的順序,但不是在圖中。奇怪的。 – crangos 2010-03-03 23:57:43

+7

ggplot2要求我改變這兩個級別的順序(見上面)以及數據幀值的順序。 df < - df [nrow(df):1,]#reverse – crangos 2010-03-04 00:13:59

7

所以你想要什麼,R中的詞彙,只是改變標籤對於給定的因子變量(即,保留數據以及與作爲因子水平維持不變)。

df$letters = factor(df$letters, labels=c("d", "c", "b", "a")) 

因爲你想只改變數據點到標籤映射,而不是數據或因素架構(數據點是如何分級成單獨的垃圾箱或因子值,它可能有助於瞭解如何。該映射最初設置在最初創建的因子

的規則是簡單的:

  • 標籤由索引值映射到水平(即,在水平的值 [2]給出的標籤,實驗室EL [2]);
  • 可以明確設置因子水平,方法是通過 級別的參數傳入;或
  • 如果沒有值的水平參數提供,默認 值用於哪個是結果在(用於數據參數)傳遞的數據矢量 主叫獨特;
  • 標籤可以通過標籤參數顯式設置;或
  • 如果沒有值的標籤參數提供,則使用默認值 這僅僅是水平矢量
+1

我不知道爲什麼這不是被接受的答案。這是更多的信息。 – Rambatino 2014-04-12 10:57:05

+7

如果您使用這種方法,您的數據將被錯誤標記。 – Nazer 2014-05-13 14:30:05

+0

@Nazer謝謝,修正 – rawr 2014-11-19 05:23:51

19

多一些,只是備案

## reorder is a base function 
df$letters <- reorder(df$letters, new.order=letters[4:1]) 

library(gdata) 
df$letters <- reorder.factor(df$letters, letters[4:1]) 

您可能會所以找到有用的Relevelcombine_factor

+2

您的第一個答案對我而言不適用。但是這個工作原理:'重新排序(df $ letters,seq(4,1))' – 2015-08-29 22:05:16

+0

我有一個非常奇怪的情況,其中'order'在一個數據集上工作,而不在另一個數據集上。在另一個數據集上,它會拋出一個錯誤「tapply中的錯誤(X = X,INDEX = x,FUN = FUN,...):參數」X「丟失,沒有默認值。不確定這個問題的解決方案是什麼。我找不到數據集之間的任何相關差異。 – Deleet 2015-12-27 21:49:38

5

處理R中的因素是相當奇特的工作,我必須承認......在對因子水平進行重新排序時,您不會重新排序基礎數值。這裏有一個小演示:

> numbers = 1:4 
> letters = factor(letters[1:4]) 
> dtf <- data.frame(numbers, letters) 
> dtf 
    numbers letters 
1  1  a 
2  2  b 
3  3  c 
4  4  d 
> sapply(dtf, class) 
    numbers letters 
"integer" "factor" 

現在,如果你這個因素轉換爲數字,你會得到:

# return underlying numerical values 
1> with(dtf, as.numeric(letters)) 
[1] 1 2 3 4 
# change levels 
1> levels(dtf$letters) <- letters[4:1] 
1> dtf 
    numbers letters 
1  1  d 
2  2  c 
3  3  b 
4  4  a 
# return numerical values once again 
1> with(dtf, as.numeric(letters)) 
[1] 1 2 3 4 

正如你可以看到... ...通過改變水平,你只能更改級別(誰會說,呃?),而不是數值!但是,當您使用factor函數@Jonathan Chang建議時,會發生一些不同的情況:您自己更改數值。

您再次收到錯誤的原因是因爲您做了levels,然後嘗試使用factor對其進行驗證。不要這樣做!做不是使用levels或者你會搞砸(除非你確切知道你在做什麼)。

一個律」建議:避免用相同的名稱爲R的對象命名的對象(df是F分佈密度函數,letters給人小寫字母)。在這種特殊情況下,你的代碼不會有問題,但有時可能會......但這會造成混淆,我們不希望這樣做,我們呢?!? =)

相反,使用這樣的事情(我會從再次開始)去:

> dtf <- data.frame(f = 1:4, g = factor(letters[1:4])) 
> dtf 
    f g 
1 1 a 
2 2 b 
3 3 c 
4 4 d 
> with(dtf, as.numeric(g)) 
[1] 1 2 3 4 
> dtf$g <- factor(dtf$g, levels = letters[4:1]) 
> dtf 
    f g 
1 1 a 
2 2 b 
3 3 c 
4 4 d 
> with(dtf, as.numeric(g)) 
[1] 4 3 2 1 

請注意,您也可以命名你data.framedfletters代替g,和結果將是確定的。實際上,這段代碼與您發佈的代碼完全相同,只是名稱已更改。這部分factor(dtf$letter, levels = letters[4:1])不會拋出錯誤,但它可能會混淆!

徹底閱讀?factor說明書! factor(g, levels = letters[4:1])factor(g, labels = letters[4:1])之間有什麼區別?有什麼和levels(g) <- letters[4:1]g <- factor(g, labels = letters[4:1])相似?

你可以把ggplot的語法,所以我們可以幫助你在這一個更多!

乾杯!

編輯:

ggplot2實際上需要改變這兩個層面和價值觀?嗯......我會把這一個挖出來......

2

由於這個問題是最後一次活動,Hadley發佈了他的新操作包forcats,我發現它非常有用。從OP的數據幀的例子:

levels(df$letters) 
# [1] "a" "b" "c" "d" 

爲扭轉水平:

library(forcats) 
fct_rev(df$letters) %>% levels 
# [1] "d" "c" "b" "a" 

要添加更多的級別:

fct_expand(df$letters, "e") %>% levels 
# [1] "a" "b" "c" "d" "e" 

還有更多有用的fct_xxx()功能。

+0

這仍然可用嗎? – 2016-11-14 00:31:10

+1

當然,請看[這裏](https://blog.rstudio.org/2016/08/31/forcats-0-1-0/)。 – Joe 2016-11-14 03:01:07

+0

您想編寫如下代碼:'df%>%mutate(letters = fct_rev(letters))'。 – jazzurro 2016-12-22 15:00:01

2

我想添加其他情況下的水平可能是攜帶數字非常久遠的一些特殊字符的字符串:像下面的例子

df <- data.frame(x = c("15-25", "0-4", "5-10", "11-14", "100+")) 

x默認級別爲:

df$x 
# [1] 15-25 0-4 5-10 11-14 100+ 
# Levels: 0-4 100+ 11-14 15-25 5-10 

這裏,如果我們想根據數值重新排列因子水平,而不明確寫出水平,我們可以做的是

library(gtools) 
df$x <- factor(df$x, levels = mixedsort(df$x)) 

df$x 
# [1] 15-25 0-4 5-10 11-14 100+ 
# Levels: 0-4 5-10 11-14 15-25 100+ 
as.numeric(df$x) 
# [1] 4 1 2 3 5 

我希望這可以被視爲未來讀者的有用信息。

相關問題