2014-09-22 5 views
0

Я хочу, чтобы droplevels dataframe (пожалуйста, не отмечайте этот вопрос как дубликат :)). Учитывая, что все доступные методы доступны только один. Что я делаю не так? Пример:R Факторы передачи данных

> df = data.frame(x = (c("a","b","c")),y=c("d","e","f")) 
> class(df$x) 
[1] "factor" 
> levels(df$x) 
[1] "a" "b" "c" 

Метод 1 не работает:

> df1 = droplevels(df) 
> class(df1$x) 
[1] "factor" 
> levels(df1$x) 
[1] "a" "b" "c" 

Метод 2 не работает:

> df2 = as.data.frame(df, stringsAsFactors = FALSE) 
> class(df2$x) 
[1] "factor" 
> levels(df2$x) 
[1] "a" "b" "c" 

Способ 3 не работает:

> df3 = df 
> df3$x = factor(df3$x) 
> class(df3$x) 
[1] "factor" 
> levels(df3$x) 
[1] "a" "b" "c" 

Метод 4, наконец, работает :

> df4 = df 
> df4$x = as.vector(df4$x) 
> class(df4$x) 
[1] "character" 
> levels(df4$x) 
NULL 

Во время работы я думаю, что метод 4 является наименее элегантным. Можете ли вы помочь мне отладить это? Большое спасибо

EDIT: Следующие комментарии и ответы: Я хочу, чтобы удалить факторную структуру из кадра данных, а не только droplevels

+4

Итак, когда вы говорите, что вы хотите 'droplevels' вы на самом деле просто означает, что вы хотите, чтобы преобразовать переменный фактор Название переменной характер. Если это так, метод 4 является единственным систематически правильным выбором. «droplevels» удаляет ненаблюдаемые уровни из фактора, но в вашем тестовом примере вы наблюдаете все уровни, поэтому ничто не отбрасывается. Если вы не хотите, чтобы они были факторами в первую очередь, используйте 'df = data.frame (x = (c (« a »,« b »,« c »)), y = c (« d », «e», «f»), strAsAsFactors = FALSE). Метод 2 не работает, поскольку они уже являются факторами в этой точке. Что * точно * ваша цель? – MrFlick

+0

@MrFlick, спасибо за объяснение, однако все еще странно, что метод 2 не работает – MasterJedi

+0

@YujiaHu Не странно. Если вы передаете 'as.data.frame', то data.frame все, что он делает, - это отрегулировать атрибут класса и (возможно) имена строк. – joran

ответ

4

«Dropping levels» означает избавление от неиспользуемых уровней факторов, но сохранение объекта как класса factor. Вы ищете способ, чтобы преобразовать все столбцы фактора в столбцы символов:

> df2 = data.frame(lapply(df, 
      function(x) if (is.factor(x)) as.character(x) else x), 
       stringsAsFactors = FALSE) 
> lapply(df2, class) 
$x 
[1] "character" 

$y 
[1] "character" 

> df2 
    x y 
1 a d 
2 b e 
3 c f 
4

Я предполагаю, что вы хотите:

df[] <- lapply(df, as.character) 

Это имеет два отличия из вашего кода: «[]» на LHS присвоения, который сохраняет структуру dataframe df и использование lapply. Функция droplevels только снижает посторонние уровни, но не преобразуется в вектор символов. Функция as.character не имеет метода data.frame. Он должен быть (l) привязан к каждому из векторов факторов, а не к списку фактор-векторов. Более общая функция, чтобы сделать это (во избежание ошибки в попытке принуждения на числовой вектор) будет:

makefac2char <- function(v) if(is.factor(v)){as.character(v)} else {v} 
df[] <- lapply(df, makefac2char) 
# To make a new dataframe 
df2 <- lapply(df, makefac2char) 
df2<- data.frame(df2) 

Если вы не хотите, чтобы с разрушением вместо «DF», то вам нужно обернуть data.frame вокруг lapply результатов поскольку lapply не поддерживает атрибуты. Если вы создали этот фреймворк с 'stringAsFactors = FALSE' (или установите этот параметр в .Options), вам не нужно было бы это делать на основе data.frame.

+1

Стандартное 'droplevels()' похоже, отлично работает над data.frame 'df = data.frame (x = factor (c (" a "," b "," c "), levels = letters), y = c ("d", "e", "f"), z = 1: 3); droplevels (DF) '. Не уверен, что это делает. – MrFlick

+0

Довольно уверен, что 'droplevels' действительно имеет метод data.frame. – joran

+0

Извините. Вопроситель запутался (и смутил меня) о том, что действие «дропвелов». Отредактировано, чтобы дать ему то, что он хочет, но использует неправильную функцию для достижения. Он хочет «как». –