r - مستويات عامل الإسقاط في إطار بيانات تم فصلها




dataframe r-factor (8)

لدي إطار بيانات يحتوي على عامل. عندما أقوم بإنشاء مجموعة فرعية من إطار البيانات هذا باستخدام subset() أو وظيفة فهرسة أخرى ، يتم إنشاء إطار بيانات جديد. ومع ذلك ، يحتفظ متغير العامل بكافة مستوياته الأصلية - حتى عندما لا يكون موجودًا في إطار البيانات الجديد.

هذا يخلق الصداع عند القيام بالتآمر أو استخدام وظائف تعتمد على مستويات العوامل.

ما هي الطريقة الأكثر إيجازًا لإزالة المستويات من عامل في إطار البيانات الجديد؟

هنا مثالى

df <- data.frame(letters=letters[1:5],
                    numbers=seq(1:5))

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

subdf <- subset(df, numbers <= 3)
##   letters numbers
## 1       a       1
## 2       b       2
## 3       c       3    

## but the levels are still there!
levels(subdf$letters)
## [1] "a" "b" "c" "d" "e"

إذا كنت لا تريد هذا السلوك ، فلا تستخدم العوامل ، استخدم متجهات الحروف بدلاً من ذلك. أعتقد أن هذا أكثر منطقية من ترقيع الأمور بعد ذلك. جرب ما يلي قبل تحميل بياناتك باستخدام read.table أو read.csv :

options(stringsAsFactors = FALSE)

العيب هو أنك مقيد بالترتيب الأبجدي. (إعادة الترتيب هو صديقك لمؤامرات)


إنها مشكلة معروفة ، ويتم توفير علاج واحد ممكن من drop.levels() في حزمة gdata حيث يصبح المثال الخاص بك

> drop.levels(subdf)
  letters numbers
1       a       1
2       b       2
3       c       3
> levels(drop.levels(subdf)$letters)
[1] "a" "b" "c"

هناك أيضًا الدالة dropUnusedLevels في حزمة Hmisc . ومع ذلك ، فإنها لا تعمل إلا من خلال تغيير عامل مجموعة فرعية [ ولا ينطبق هنا.

وكنتيجة طبيعية ، فإن النهج المباشر على أساس كل عمود هو as.factor(as.character(data)) بسيط as.factor(as.character(data)) :

> levels(subdf$letters)
[1] "a" "b" "c" "d" "e"
> subdf$letters <- as.factor(as.character(subdf$letters))
> levels(subdf$letters)
[1] "a" "b" "c"

كتبت وظائف فائدة للقيام بذلك. الآن وأنا أعلم أن drop.levels gdata ، يبدو مشابها جدا. ها هم (من here ):

present_levels <- function(x) intersect(levels(x), x)

trim_levels <- function(...) UseMethod("trim_levels")

trim_levels.factor <- function(x)  factor(x, levels=present_levels(x))

trim_levels.data.frame <- function(x) {
  for (n in names(x))
    if (is.factor(x[,n]))
      x[,n] = trim_levels(x[,n])
  x
}

كل ما عليك القيام به هو تطبيق العامل () على المتغير الخاص بك مرة أخرى بعد الغطس:

> subdf$letters
[1] a b c
Levels: a b c d e
subdf$letters <- factor(subdf$letters)
> subdf$letters
[1] a b c
Levels: a b c

تصحيح

من مثال عامل الصفحة:

factor(ff)      # drops the levels that do not occur

لإسقاط المستويات من جميع أعمدة العوامل في مخطط البيانات ، يمكنك استخدام:

subdf <- subset(df, numbers <= 3)
subdf[] <- lapply(subdf, function(x) if(is.factor(x)) factor(x) else x)

منذ R الإصدار 2.12 ، هناك droplevels() .

levels(droplevels(subdf$letters))

موضوع مثير جدا للاهتمام ، وأنا أحب ولا سيما فكرة مجرد عامل subelection مرة أخرى. كان لدي مشكلة مماثلة من قبل ، وأنا فقط تحولت إلى شخصية ومن ثم العودة إلى العامل.

   df <- data.frame(letters=letters[1:5],numbers=seq(1:5))
   levels(df$letters)
   ## [1] "a" "b" "c" "d" "e"
   subdf <- df[df$numbers <= 3]
   subdf$letters<-factor(as.character(subdf$letters))

هنا طريقة أخرى ، والتي أعتقد أنها تعادل نهج factor(..) :

> df <- data.frame(let=letters[1:5], num=1:5)
> subdf <- df[df$num <= 3, ]

> subdf$let <- subdf$let[ , drop=TRUE]

> levels(subdf$let)
[1] "a" "b" "c"

هنا طريقة لفعل ذلك

varFactor <- factor(letters[1:15])
varFactor <- varFactor[1:5]
varFactor <- varFactor[drop=T]




r-faq