Değerlerin sırasını değiştirmeden bir faktörün seviyelerini yeniden sıralayın


124

Bazı sayısal değişkenler ve bazı kategorik factordeğişkenler içeren veri çerçevem ​​var . Bu faktörler için düzeylerin sırası, olmasını istediğim şekilde değil.

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

Seviyelerin sırasını değiştirirsem, harfler artık karşılık gelen numaralarıyla birlikte olmaz (verilerim bu noktadan itibaren tamamen anlamsızdır).

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

Sadece seviye sırasını değiştirmek istiyorum , bu yüzden grafik çizerken çubuklar istenen sırada gösterilir - bu varsayılan alfabetik sıradan farklı olabilir.


1
Soruda crangos'un gösterdiği gibi, seviyelere atamanın (...) neden veri çerçevesindeki girişlerin sırasını değiştirdiği konusunda biri bana bir ipucu verebilir mi? Bana çok sezgisel ve istenmeyen görünüyor. Bugün kendimden kaynaklanan bir sorunu çözmek için biraz zaman harcadım. Bu davranış için yine de göremediğim bir neden olabileceğini veya en azından bunun neden olduğuna dair makul bir açıklama olabileceğini düşünüyorum.
Anton

Yanıtlar:


120

levelsArgümanını kullanın 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
Teşekkür ederim, bu işe yaradı. Garip bir nedenden ötürü, ggplot artık açıklamadaki sırayı doğru şekilde değiştirdi, ancak olay örgüsünde değil. Tuhaf.
crangos

7
ggplot2, hem seviyelerin sırasını (yukarıya bakın) hem de veri çerçevesinin değerlerinin sırasını değiştirmemi istedi. df <- df [nrow (df): 1,] # ters
crangos

@crangos, bence ggplot seviyelerin alfabetik sıralanmasını kullanıyor ve bazen özel faktör seviyelerini yok sayıyor. Lütfen onaylayın ve sürüm numarasını ekleyin.
smci

22

biraz daha, sadece kayıt için

## 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])

Ayrıca Relevel ve comb_factor'ı da yararlı bulabilirsiniz .


2
İlk cevabın benim için işe yaramıyor. Ama bu işe yarıyor:reorder(df$letters, seq(4,1))
Alex Holcombe

1
"Yeniden sipariş" in bir veri kümesinde değil, başka bir veri kümesinde çalıştığı çok garip bir durum var. Diğer veri kümesinde, "Tapply'de hata (X = X, INDEX = x, FUN = FUN, ...):" X "bağımsız değişkeni, varsayılan yok" hatası verir. Bu sorunun çözümünün ne olduğundan emin değilim. Veri kümeleri arasında alakalı bir fark bulamıyorum.
CoderGuy123

10

Bu soru en son aktif olduğu için Hadley forcatsfaktörleri manipüle etmek için yeni paketini yayınladı ve ben onu son derece yararlı buluyorum. OP'nin veri çerçevesinden örnekler:

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

Seviyeleri ters çevirmek için:

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

Daha fazla seviye eklemek için:

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

Ve daha birçok kullanışlı fct_xxx()işlev.


Bu hala mevcut mu?
Joshua Rosenberg

1
Böyle bir kod yazmak istiyorum: df %>% mutate(letters = fct_rev(letters)).
jazzurro

9

Dolayısıyla, R sözlüğünde istediğiniz şey, yalnızca belirli bir faktör değişkeni için etiketleri değiştirmektir (yani, verileri ve faktör düzeylerini değiştirmeden bırakmak ).

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

Verileri veya faktör şemasını değil, yalnızca veri noktasından etikete eşlemeyi değiştirmek istediğinizde (veri noktalarının ayrı bölmelere veya faktör değerlerine nasıl gruplandırıldığı), başlangıçta oluşturduğunuzda eşlemenin başlangıçta nasıl ayarlandığını bilmenize yardımcı olabilir. faktör.

kurallar basit:

  • etiketler, indeks değerine göre seviyelere eşlenir (yani, [2] seviyelerindeki değere etiket [2] etiketi verilir);
  • faktör düzeyleri, düzeyler bağımsız değişkeni aracılığıyla iletilerek açık bir şekilde ayarlanabilir ; veya
  • düzeyler bağımsız değişkeni için bir değer sağlanmadıysa, varsayılan değer kullanılır ve bu, iletilen veri vektöründe ( veri bağımsız değişkeni için) benzersiz olanı çağıran sonuçtur ;
  • etiketler, etiketler bağımsız değişkeni aracılığıyla açıkça ayarlanabilir; veya
  • etiketler bağımsız değişkeni için değer sağlanmadıysa, yalnızca düzey vektörü olan varsayılan değer kullanılır

1
Bunun neden kabul edilen cevap kadar oylanmadığını bilmiyorum. Bu çok daha bilgilendirici.
Rambatino

12
Bu yaklaşımı kullanırsanız, verileriniz yanlış etiketlenir.
Nazer

4
aslında evet, bununla ne yapacağımı bilmiyorum, cevap, çizim uğruna verileri yanlış etiketlemeyi düşünüyor gibi görünüyor? öf. orijinaline geri alındı. kullanıcılar dikkat
rawr

7

R'deki faktörlerle uğraşmak oldukça tuhaf bir iş, itiraf etmeliyim ... Faktör seviyelerini yeniden sıralarken, altta yatan sayısal değerleri yeniden düzenlemiyorsunuz. İşte küçük bir gösteri:

> 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" 

Şimdi, bu faktörü sayısal değere dönüştürürseniz, şunu elde edersiniz:

# 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

Gördüğünüz gibi ... seviyeleri değiştirerek, sayısal değerleri değil, yalnızca seviyeleri (kim söyler ki, eh?) Değiştirirsiniz! Ancak, factor@Jonathan Chang'ın önerdiği işlevi kullandığınızda , farklı bir şey olur: sayısal değerleri kendiniz değiştirirsiniz.

Bir kez daha hata alıyorsun çünkü yapıyorsun levelsve sonra onu yeniden seviyelendirmeye çalışıyorsun factor. Yapma !!! Do not kullanmak levelsveya işleri berbat olacak (ne yaptığınızı tam olarak bilmek sürece).

Bir lil 'öneri: nesnelerinizi R'nin nesneleri ile aynı isimle adlandırmaktan kaçının ( dfF dağılımı için yoğunluk fonksiyonudur, lettersküçük harfli alfabe harfleri verir). Bu özel durumda, kodunuz hatalı olmayacaktır, ancak bazen olabilir ... ama bu kafa karışıklığı yaratabilir ve biz bunu istemiyoruz, değil mi?!? =)

Bunun yerine, şuna benzer bir şey kullanın (bir kez daha baştan başlayacağım):

> 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

Ayrıca sizi adlandırabilir geldiğini hatırlatırız data.frameile dfve lettersyerine gve sonuç olumlu olacaktır. Aslında, bu kod gönderdiğiniz kodla aynıdır, sadece isimler değiştirilir. Bu kısımfactor(dtf$letter, levels = letters[4:1]) bir hata vermez, ancak kafa karıştırıcı olabilir!

?factorKılavuzu iyice okuyun ! Arasındaki fark nedir factor(g, levels = letters[4:1])ve factor(g, labels = letters[4:1])? Benzer ne var levels(g) <- letters[4:1]ve g <- factor(g, labels = letters[4:1])?

Ggplot sözdizimi koyabilirsiniz, böylece size bu konuda daha fazla yardımcı olabiliriz!

Alkış !!!

Düzenle:

ggplot2aslında hem seviyeleri hem de değerleri değiştirmeyi gerektiriyor mu? Hm ... Bunu çıkaracağım ...


3

Seviyelerin bazı özel karakterlerle birlikte sayıları taşıyan dizeler olabileceği başka bir durum eklemek istiyorum: aşağıdaki örnek gibi

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

Varsayılan seviyeleri x:

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

Burada, faktör seviyelerini sayısal değere göre yeniden sıralamak istersek, seviyeleri açıkça yazmadan yapabileceğimiz şey şudur:

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

Umarım bu, gelecekteki okuyucular için faydalı bir bilgi olarak kabul edilebilir.


0

Verilen bir veri çerçevesinin faktörlerini yeniden sıralamak için benim fonksiyonum:

reorderFactors <- function(df, column = "my_column_name", 
                           desired_level_order = c("fac1", "fac2", "fac3")) {

  x = df[[column]]
  lvls_src = levels(x) 

  idxs_target <- vector(mode="numeric", length=0)
  for (target in desired_level_order) {
    idxs_target <- c(idxs_target, which(lvls_src == target))
  }

  x_new <- factor(x,levels(x)[idxs_target])

  df[[column]] <- x_new

  return (df)
}

Kullanımı: reorderFactors(df, "my_col", desired_level_order = c("how","I","want"))

Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.