2009-10-08 1 views
56

Есть ли определенный R-gotcha, который вы действительно удивились в один прекрасный день? Я думаю, мы все выиграем от их совместного использования.Какая самая большая R-gotcha, с которой вы столкнулись?

Вот мой: в индексировании списка my.list[[1]] не my.list[1]. Узнал это в первые дни Р.

+9

Есть намного больше подводных камней, больших и малых, в 'The R Inferno' http://www.burns-stat.com/pages/Tutor/R_inferno .pdf –

+4

Пробел имеет значение в инструкции if-else. 'Ошибка: неожиданно 'else' в" else "' выскочит, когда вы поместите новую строку после фигурной скобки в инструкции if: 'if {...} \ n else {...}'. – TMS

+0

Функция 'выбрать'. 'select (n, k)' не является числом подмножеств 'k'-элементов набора' n'-элементов.Например, «выберите (-4,2) == 10'. – Flounderer

ответ

32

Удаление строк в dataframe приведет к не-однозначно названные строки будут добавлены, которые затем ошибки вне:

> a<-data.frame(c(1,2,3,4),c(4,3,2,1)) 
> a<-a[-3,] 
> a 
    c.1..2..3..4. c.4..3..2..1. 
1    1    4 
2    2    3 
4    4    1 
> a[4,1]<-1 
> a 
Error in data.frame(c.1..2..3..4. = c("1", "2", "4", "1"), c.4..3..2..1. = c(" 4", : 
    duplicate row.names: 4 

Так что здесь происходит:

  1. создается четыре строки data.frame, поэтому имена розеток c (1,2,3,4)

  2. Третья строка удалена, поэтому имена розеток c (1,2,4)

  3. Добавлена ​​четвертая строка, и R автоматически устанавливает имя строки, равную индексу i.e. 4, поэтому имена строк c (1,2,4,4). Это незаконно, потому что имена строк должны быть уникальными. Я не понимаю, почему этот тип поведения должен быть разрешен R. Мне кажется, что R должно предоставить уникальное имя строки.

+2

Интересно. Я использую R и его предшественников S с 1988 года, и я никогда раньше этого не видел! –

+0

Ничего себе. Это очень странно. Вы можете это объяснить? – Shane

+11

Итак, вот что происходит здесь: 1. Создан четырехрядный data.frame, поэтому имена розеток c (1,2,3,4) 2. Третья строка удалена, поэтому имена ростов - c (1,2,4) 3. Добавлена ​​четвертая строка, и R автоматически устанавливает имя строки, равную индексу, то есть 4, поэтому имена строк c (1,2,4,4). Это незаконно, потому что имена строк должны быть уникальными. Я не понимаю, почему этот тип поведения должен быть разрешен Р. Мне кажется, что R должно предоставить уникальное имя строки. –

6
  1. случайно листинг исходного кода функции, забывая включать пустые круглые скобки: например, "ls" против "ls()"

  2. true & false не разрезать его как предопределенные константы, как в Matlab, C++, Java, Python; должен использовать TRUE & FALSE

  3. Невидимые возвращаемые значения: напр. «.packages()» ничего не возвращает, а „(.packages())“ возвращает символ вектор пакета базовых имен

+0

R автоматически завершает работу, поэтому na.rm = T работает, а также na.rm = TRUE. Я всегда предпочитаю последнее, но для удобочитаемости. – Vince

+10

Ну, это не строго эквивалентно. Вы можете перезаписать T, но TRUE установлен. Попробуйте подтвердить следующее: {T <- FALSE; T}. Очень опасно! Итак, Стюарт прав: вам нужно быть осторожным с вашими истинными/ложными значениями. – Shane

32

Забыв раскрывающееся = FALSE аргумент в Подменю матрицы вплоть до одного измерения и тем самым опуская класс объектов, а также:

R> X <- matrix(1:4,2) 
R> X 
    [,1] [,2] 
[1,] 1 3 
[2,] 2 4 
R> class(X) 
[1] "matrix" 
R> X[,1] 
[1] 1 2 
R> class(X[,1]) 
[1] "integer" 
R> X[,1, drop=FALSE] 
    [,1] 
[1,] 1 
[2,] 2 
R> class(X[,1, drop=FALSE]) 
[1] "matrix" 
R> 
13

Забывая, что strptime() и друзья возвращаются POSIXt POSIXlt где length() всегда девять - преобразование в POSIXct помогает:

R> length(strptime("2009-10-07 20:21:22", "%Y-%m-%d %H:%M:%S")) 
[1] 9 
R> length(as.POSIXct(strptime("2009-10-07 20:21:22", "%Y-%m-%d %H:%M:%S"))) 
[1] 1 
R> 
+2

... теперь он возвращает длину 1 в R 2.14.0 (и, возможно, некоторые более ранние версии) ... – Tommy

34

Автоматическое создание факторов при загрузке данных. Вы бездумно относитесь к столбцу в фрейме данных как к символам, и это хорошо работает, пока вы не сделаете что-то вроде попытки изменить значение до уровня, который не является уровнем. Это приведет к предупреждению, но оставьте свой кадр данных с NA в нем ...

Когда что-то неожиданно не так в вашем R-скрипте, убедитесь, что факторы не виноваты.

+7

Правильно, но вы можете использовать 'options ("strAsAsFactors" = FALSE) 'в вашем файле запуска (s), чтобы изменить это. –

+9

@ Dirk все хорошо, пока вы не отправите часть кода кому-то с другим .Rprofile (случилось со мной на этой неделе;) – baptiste

+1

Это на самом деле происходит не только при чтении файла, но и при использовании 'data.frame' конструктор. Убила меня из-за многих раз. – prabhasp

18

Всегда проверяйте, что происходит, когда у вас есть NA!

Одна вещь, за которую мне всегда нужно уделять пристальное внимание (после многих болезненных переживаний) значение NA. Функции R просты в использовании, но ни один из способов программирования не справится с проблемами с вашими данными.

Например, любая операция векторного вектора с NA равна NA. Это «удивительно» на первый взгляд:

> x <- c(1,1,2,NA) 
> 1 + NA 
[1] NA 
> sum(x) 
[1] NA 
> mean(x) 
[1] NA 

Это экстраполируется на другие функции более высокого уровня.

Иными словами, недостающие значения часто имеют такое же значение, как измеренные значения по умолчанию. У многих функций есть na.rm=TRUE/FALSE defaults; стоит потратить некоторое время на решение, как интерпретировать эти настройки по умолчанию.

Редактировать 1: Marek делает отличную точку. Значения NA также могут вызывать запутанное поведение в индексах. Например:

> TRUE && NA 
[1] NA 
> FALSE && NA 
[1] FALSE 
> TRUE || NA 
[1] TRUE 
> FALSE || NA 
[1] NA 

Это также верно, когда вы пытаетесь создать условное выражение (для если заявление):

> any(c(TRUE, NA)) 
[1] TRUE 
> any(c(FALSE, NA)) 
[1] NA 
> all(c(TRUE, NA)) 
[1] NA 

Когда эти значения NA в конечном итоге, как ваши векторные индексы, многие неожиданные вещи могут последовать. Это все хорошее поведение для R, потому что это означает, что вы должны быть осторожны с отсутствующими значениями. Но это может вызвать серьезные головные боли в начале.

+2

Он болит в подписи, например. '(1: 3) [c (TRUE, FALSE, NA)]' дает '1, NA'. Это легко ловить в ловушку, когда вы создаете логический вектор для содержащегося в NA вектора '(1: 3) [c (1,2, NA) <2]'. – Marek

3

Исходя из составленного языка и Matlab, я получил иногда путают о фундаментальном аспекте функций в функциональных языках: они должны быть определены , прежде чем они использовали! Недостаточно просто для их анализа синтаксисом R-интерпретатора. Это в основном поднимает голову, когда вы используете вложенные функции.

В Matlab вы можете сделать:

function f1() 
    v1 = 1; 
    v2 = f2(); 
    fprintf('2 == %d\n', v2); 

    function r1 = f2() 
    r1 = v1 + 1 % nested function scope 
    end 
end 

Если вы попытаетесь сделать то же самое в R, вы должны поместить вложенную функцию первой, или вы получите сообщение об ошибке! Просто потому, что вы определили функцию, она не находится в пространстве имен, пока она не будет назначена переменной! С другой стороны, функция может ссылаться на переменную с , а не.

f1 <- function() { 
    f2 <- function() { 
    v1 + 1 
    } 

    v1 <- 1 

    v2 = f2() 

    print(sprintf("2 == %d", v2)) 
} 
+1

«Функция может ссылаться на переменную, которая еще не определена»: к * объекту *, который еще не определен, включая функцию! Если вы измените 'v1 + 1' на' f3() 'в вашем примере, а затем определите функцию' f3' до вызова 'f2', она все равно работает нормально. –

5

Например, число 3,14 является численной константой, но выражения +3.14 и -3,14 призывы к функциям + и -:

> class(quote(3.14)) 
[1] "numeric" 
> class(quote(+3.14)) 
[1] "call" 
> class(quote(-3.14)) 
[1] "call" 

См Раздел 13.2 в John Chambers книги Software for Data Analysis - Programming with R

+0

Это интересно, но действительно ли это когда-либо создавало проблемы для вас на примере реальной жизни? –

40

[Хедли указал на это in a comment.]

При использовании в качестве последовательности Ind ex для итерации, лучше использовать функцию seq_along(), а не что-то вроде 1:length(x).

Здесь я создаю вектор и оба подхода возвращают то же самое:

> x <- 1:10 
> 1:length(x) 
[1] 1 2 3 4 5 6 7 8 9 10 
> seq_along(x) 
[1] 1 2 3 4 5 6 7 8 9 10 

Теперь сделать вектор NULL:

> x <- NULL 
> seq_along(x) # returns an empty integer; good behavior 
integer(0) 
> 1:length(x) # wraps around and returns a sequence; this is bad 
[1] 1 0 

Это может вызвать некоторую путаницу в цикле:

> for(i in 1:length(x)) print(i) 
[1] 1 
[1] 0 
> for(i in seq_along(x)) print(i) 
> 
+0

По этой же причине полезно использовать 'seq' вместо': 'вообще .... –

3

Шахта с сегодняшнего дня: qnorm() принимает вероятности и pnorm() принимает Quantiles.

+2

, потому что имена обозначают то, что они возвращают, а не то, что они берут. Вы предпочли бы грех() брать коэффициенты? – John

+2

Успокойся на меня, это было мое первое представление :) –

23

Прежде всего позвольте мне сказать, что я понимаю фундаментальные проблемы представления чисел в двоичной системе. Тем не менее, одна проблема, которая, по моему мнению, может быть легко улучшена, - это представление чисел, когда десятичное значение выходит за пределы типичной области представления R.

x <- 10.2 * 100 
x 
1020 
as.integer(x) 
1019 

Я не возражаю, если результат представлен как целое число, если оно действительно может быть представлено как целое число. Например, если значение действительно было 1020, то печать, которая для x была бы прекрасной. Но что-то столь же простое, как 1020.0 в этом случае при печати x, сделало бы более очевидным, что значение не было целым и не представлялось как единое целое. R должен по умолчанию указывать какую-либо индикацию, когда имеется чрезвычайно маленький десятичный компонент, который не представлен.

+1

Сочувствую, но это действительно сложно. За все время печати все до полной точности вы можете привести пример языка, который делает это лучше? (Это реальный, а не риторический вопрос ...) –

+1

Я не думаю, что любой язык, который я использую, обрабатывает это замечательно, но я думаю, что текущий метод R о худшем, потому что он отображает с плавающей точкой, как если бы он был целым, , Простое отображение какой-либо плавающей точки, по крайней мере, было бы лучше, но тогда это могло бы создать необходимость в количестве десятичных знаков. На самом деле было бы полезно иметь вышеуказанное как 1.0199e3. Или, в альтернативной ситуации с чем-то вроде 81.00000001, представляющим 8.10e1 как неожиданный результат может намекнуть, что есть много больше десятичных знаков. Есть много лучших способов. Менее хуже. – John

+1

О, и большинство интерпретируемых языков программирования просто попытаются напечатать все число, если это возможно. Они, по крайней мере, будут отображать с плавающей точкой плавучую точку. – John

19

Это может быть досадно, если необходимо учитывать комбинации NA, NaN и Inf. Они ведут себя по-разному, и тесты для одного не обязательно будет работать для других:

> x <- c(NA,NaN,Inf) 
> is.na(x) 
[1] TRUE TRUE FALSE 
> is.nan(x) 
[1] FALSE TRUE FALSE 
> is.infinite(x) 
[1] FALSE FALSE TRUE 

Однако самый безопасный способ протестировать любой из этих смутьянов является:

> is.finite(x) 
[1] FALSE FALSE FALSE 
+7

Интересно ... Я всегда думал о «NA» как «Я еще не знаю». но моя интерпретация не подходит с 'is.infinite (NA)' и 'is.finite (NA)' return 'FALSE': я ожидал' NA'. – mariotomo

13

round функция всегда округляет до четного числа.

> round(3.5) 
[1] 4 

> round(4.5) 
[1] 4 
+3

Я уверен, что это плавающая точка _gotcha_, а не R _gotcha_. – Marek

+1

Википедия имеет некоторую [полезную информацию] (http://en.wikipedia.org/wiki/Rounding#Round_half_to_even) об этом типе округления, что объясняется спецификациями с плавающей точкой IEEE 754. – Iterator

10

Я удивлен, что никто не упомянул об этом, но:

T & F может быть переопределение, TRUE & FALSE нет.

Пример:

x <- sample(c(0,1,NA), 100, T) 
T <- 0:10 

mean(x, na.rm=T) 
# Warning in if (na.rm) x <- x[!is.na(x)] : 
# the condition has length > 1 and only the first element will be used 
# Calls: mean -> mean.default 
# [1] NA 

plot(rnorm(7), axes=T) 
# Warning in if (axes) { : 
# the condition has length > 1 and only the first element will be used 
# Calls: plot -> plot.default 
# Warning in if (frame.plot) localBox(...) : 
# the condition has length > 1 and only the first element will be used 
# Calls: plot -> plot.default 

[править] ctrf+F трюк меня. Shane mention about this in his comment.

+0

И очевидное забавное следствие: put 'T <- FALSE; F <- TRUE' внутри чей-то ~/.Rprofile – smci

5

Частичное совпадение в операторе $: Это относится к спискам, но и на data.frame

df1 <- data.frame(foo=1:10, foobar=10:1) 
df2 <- data.frame(foobar=10:1) 

df1$foo # Correctly gets the foo column 
df2$foo # Expect NULL, but this returns the foobar column!!! 

# So, should use double bracket instead: 
df1[["foo"]] 
df2[["foo"]] 

[[ оператор также имеет exact флаг, но, к счастью, TRUE по умолчанию.

Частичное совпадение также влияет attr:

x1 <- structure(1, foo=1:10, foobar=10:1) 
x2 <- structure(2, foobar=10:1) 

attr(x1, "foo") # Correctly gets the foo attribute 
attr(x2, "foo") # Expect NULL, but this returns the foobar attribute!!! 

# So, should use exact=TRUE 
attr(x1, "foo", exact=TRUE) 
attr(x2, "foo", exact=TRUE) 
12

Math на целых числах, немного отличается от двойников (а иногда и сложный странно тоже)

UPDATE Они зафиксировали некоторые вещи в R 2.15

1^NA  # 1 
1L^NA  # NA 
(1+0i)^NA # NA 

0L %/% 0L # 0L (NA from R 2.15) 
0 %/% 0 # NaN 
4L %/% 0L # 0L (NA from R 2.15) 
4 %/% 0 # Inf 
4

Работая со списками, есть несколько неинтуитивных вещей:

Конечно, разница между [ и [[ подходит к концу. Для списков [ возвращает список (потенциально 1) элементов, тогда как [[ возвращает элемент внутри списка.

создание списка:

# When you're used to this: 
x <- numeric(5) # A vector of length 5 with zeroes 
# ... this might surprise you 
x <- list(5) # A list with a SINGLE element: the value 5 
# This is what you have to do instead: 
x <- vector('list', 5) # A vector of length 5 with NULLS 

Итак, как вставить NULL в списке?

x <- list("foo", 1:3, letters, LETTERS) # A sample list 
x[[2]] <- 1:5  # Put 1:5 in the second element 
# The obvious way doesn't work: 
x[[2]] <- NULL  # This DELETES the second element! 
# This doesn't work either: 
x[2] <- NULL  # This DELETES the second element! 

# The solution is NOT very intuitive: 
x[2] <- list(NULL) # Put NULL in the second element 

# Btw, now that we think we know how to delete an element: 
x <- 1:10 
x[[2]] <- NULL # Nope, gives an ERROR! 
x <- x[-2] # This is the only way for atomic vectors (works for lists too) 

Наконец, некоторые передовые вещи, как индексирование через вложенный список:

x <- list(a=1:3, b=list(c=42, d=13, e="HELLO"), f='bar') 
x[[c(2,3)]] # HELLO (first selects second element and then it's third element) 
x[c(2,3)] # The second and third elements (b and f) 
+0

'x [[2]] <- 1: 5' put '1: 5' во втором элементе. И чтобы расширить ваш ответ 'x [1: 2] <- 1: 2' put' 1' в первом элементе и '2' во втором,' x [1,2] 'работает для вложенного списка (второй элемент первого элемента) – Marek

+0

@Marek - Ну, я не нашел 'x [[2]]' <- 1: 5 и 'x [1: 2] <- 1: 2', что удивительно. 'x [1,2]' должен быть 'x [[c (1,2)]]', и я обновил ответ. Благодаря! – Tommy

+0

'x [2] <- 1: 5' дает мне предупреждение и ставит' 1' во второй элемент 'x'. И я ошибся в своем комментарии: у меня есть разница между 'x [c (1,2)]' (возврат 1-го и 2-го элементов) и 'x [[c (1,2)]]' (return 2nd элемент 1-го элемента). – Marek

8

Чтение в данных может быть более проблематичными, чем вы думаете. Сегодня я обнаружил, что если вы используете read.csv(), если строка в CSV-файле пуста, read.csv() автоматически пропускает ее. Это имеет смысл для большинства приложений, но если вы автоматически извлекаете данные из (например) строки 27 из нескольких тысяч файлов, а некоторые из предыдущих строк могут быть или не быть пустыми, если вы не будете осторожны, все может пойти ужасно неправильно.

я теперь использовать

data1 <- read.table(file_name, blank.lines.skip = F, sep = ",") 

При импорте данных, убедитесь, что вы делаете то, что вы на самом деле думаете, что вы делаете снова и снова и снова ...

4

Автоматическое повторение векторы ("рециркуляция") используются в качестве индексов:

R> all.numbers <- c(1:5) 
R> all.numbers 
[1] 1 2 3 4 5 
R> good.idxs <- c(T,F,T) 
R> #note unfortunate length mismatch 
R> good.numbers <- all.numbers[good.idxs] 
R> good.numbers 
[1] 1 3 4 
R> #wtf? 
R> #why would you repeat the vector used as an index 
R> #without even a warning? 
+0

Приятная находка. Я не думаю, что это когда-либо возникало в моей работе, и я работаю с множеством логических индексов ... Я не планирую программировать эту проблему, но было бы интересно узнать, где другие могут это увидеть. – Iterator

+2

Этот вид рециркуляции векторов довольно распространен в R. Я чувствую, что это смешанное благо и потенциальный источник непредвиденного поведения. –

+0

Это называется ** рециркуляция ** или ** переработка векторов **, как отметил @PaulHiemstra, и это преднамеренно, даже если результаты иногда неаккуратные. – smci

8

хитрая поведение all.equal() функция.

Одной из моих постоянных ошибок является сравнение набора чисел с плавающей запятой. У меня есть CSV, как:

... mu, tau, ... 
... 0.5, 1.7, ... 

Чтение файла и пытается подмножество данных иногда работает, иногда не - конечно, из-за снова и снова падают в ямы точки ловушки с плавающей точкой. Сначала данные содержат только целые значения, а затем они всегда преобразуются в реальные значения, вы знаете историю. Сравнение должно выполняться с помощью функции all.equal() вместо оператора ==, но, конечно, код, который я впервые написал, использовал последний подход.

Да, круто, но all.equal() возвращает TRUE равные числа, но сообщение текстовой ошибки, если это не удается:

> all.equal(1,1) 
[1] TRUE 
> all.equal(1:10, 1:5) 
[1] "Numeric: lengths (10, 5) differ" 
> all.equal(1:10, c(1:5,1:5)) 
[1] "Mean relative difference: 0.625" 

Решение использует isTRUE() функцию:

if (!isTRUE(all.equal(x, y, tolerance=doubleErrorRate))) { 
    ... 
} 

Сколько раз я получил, чтобы прочитать all.equals() описание ...

5

векторов нулевой длины имеют некоторые особенности:

R> kk=vector(mode="numeric",length=0) 
R> kk 
numeric(0) 
R> sum(kk) 
[1] 0 
R> var(kk) 
[1] NA 
+0

Обратите внимание, что 'prod (числовой (0)) == 1' тоже. Я уверен, что это обсуждалось ранее в списках рассылки r, но это хороший момент. –

7

Это одна так больно, что я потратил часы добавления комментариев к bug-report. Я не получил своего желания, но, по крайней мере, следующая версия R создаст ошибку.

R> nchar(factor(letters)) 
[1] 1 1 1 1 1 1 1 1 1 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 

Обновление: Начиная с R 3.2.0 (возможно, ранее), этот пример теперь генерирует сообщение об ошибке. Как упоминалось в комментариях ниже, фактор НЕ является вектором, а nchar() требует вектор.

R> nchar(factor(letters)) 
Error in nchar(factor(letters)) : 'nchar()' requires a character vector 
R> is.vector(factor(letters)) 
[1] FALSE 
+1

Интересно. Можете ли вы объяснить, почему это происходит? Мне кажется, что он подсчитывает символы в числовом представлении, т. Е. 9 значений 1 (1 разряд), 17 с 2 символами (для 2 цифр). – Iterator

+2

Что я узнал, так это то, что фактором является _не_ вектор, а «nchar» работает только на векторах. –

+1

Этот комментарий приходит супер послезавтра, но вышеуказанный комментарий не подходит. 'factor (letters)' не может быть «вектором», но его можно рассматривать как таковой, вы можете видеть его как вектор факторов. Первый комментарий близок к тому, что здесь происходит - внутри, факторы - целые числа: 'typeof (factor (letters))'. Таким образом, этот результат совпадает с «nchar (1: length (letters))». '1', когда у вас есть одна цифра,' 2' для двух цифр. – iled

3

Для меня это счетчик интуитивный способ, в котором при экспорте data.frame в текстовый файл с помощью write.csv, а затем импортировать его после этого вам нужно добавить дополнительный аргумент, чтобы получить точно такие же данные. кадр, как это:

write.csv(m, file = 'm.csv') 
read.csv('m.csv', row.names = 1) # Note the row.names argument 

Я также отправил this question в SO и был предложен в качестве ответа на этот Q по @BenBolker.

1

Набор функций не только работает для матриц, но и масштабируется до многомерного массива. В моих исследованиях я часто располагаю набором данных, например, температуры атмосферы. Это сохраняется в многомерном массиве с размерами x,y,level,time, отныне он называется multi_dim_array. Макет пример был бы:

multi_dim_array = array(runif(96 * 48 * 6 * 100, -50, 50), 
         dim = c(96, 48, 6, 100)) 
> str(multi_dim_array) 
#  x  y  lev time  
num [1:96, 1:48, 1:6, 1:100] 42.4 16 32.3 49.5 24.9 ... 

apply Использование можно легко получить:

# temporal mean value 
> str(apply(multi_dim_array, 4, mean)) 
num [1:100] -0.0113 -0.0329 -0.3424 -0.3595 -0.0801 ... 
# temporal mean value per gridcell (x,y location) 
> str(apply(multi_dim_array, c(1,2), mean)) 
num [1:96, 1:48] -1.506 0.4553 -1.7951 0.0703 0.2915 ... 
# temporal mean value per gridcell and level (x,y location, level) 
> str(apply(multi_dim_array, c(1,2,3), mean)) 
num [1:96, 1:48, 1:6] -3.839 -3.672 0.131 -1.024 -2.143 ... 
# Spatial mean per level 
> str(apply(multi_dim_array, c(3,4), mean)) 
num [1:6, 1:100] -0.4436 -0.3026 -0.3158 0.0902 0.2438 ... 

Это делает margin аргумент apply кажутся намного меньше счетчик интуитивно. Сначала я хочу, почему бы не использовать «row» и «col» вместо 1 и 2. Но тот факт, что он также работает для массива с большим количеством измерений, дает понять, почему использование margin, как это предпочтительнее.

+0

Почему это «гоча»? –

4

Одна из больших путаниц в R заключается в том, что [i, drop = TRUE] действительно снижает уровень фактора падения, но [i, j, drop = TRUE] - нет!

> df = data.frame(a = c("europe", "asia", "oceania"), b = c(1, 2, 3)) 
> df$a[1:2, drop = TRUE] 
[1] europe asia 
Levels: asia europe   <---- drops factor levels, works fine 
> df[1:2,, drop = TRUE]$a 
[1] europe asia 
Levels: asia europe oceania <---- does not drops factor levels! 

Для получения дополнительной информации см: drop = TRUE doesn't drop factor levels in data.frame while in vector it does