Должен ли я использовать data.frame или матрицу? - PullRequest
149 голосов
/ 01 марта 2011

Когда следует использовать data.frame, и когда лучше использовать matrix?

Оба хранят данные в прямоугольном формате, поэтому иногда неясно.

Существуют ли общие правила, когда следует использовать какой тип данных?

Ответы [ 6 ]

173 голосов
/ 01 марта 2011

Часть ответа уже содержится в вашем вопросе: вы используете фреймы данных, если можно ожидать, что столбцы (переменные) будут разных типов (числовые / символьные / логические и т. Д.).Матрицы предназначены для данных одного типа.

Следовательно, выбор матрицы / data.frame проблематичен только в том случае, если у вас есть данные одного типа.

Ответ зависит от того, что вы собираетесь делать с данными в data.frame./ матрица.Если он будет передан другим функциям, то ожидаемый тип аргументов этих функций определяет выбор.

Также:

Матрицы более эффективны с точки зрения памяти:

m = matrix(1:4, 2, 2)
d = as.data.frame(m)
object.size(m)
# 216 bytes
object.size(d)
# 792 bytes

Матрицы необходимы, если вы планируете выполнять какие-либо операции типа линейной алгебры.

Фреймы данных более удобны, если вы часто ссылаетесь на их столбцы по имени (с помощью компактного оператора $).

Фреймы данных также ИМХО лучше подходят для представления (печати) табличной информации, поскольку вы можете применять форматирование к каждому столбцу отдельно.

74 голосов
/ 01 марта 2011

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

Фреймы данных часто намного удобнее;у каждого не всегда есть только атомарные порции данных.

Обратите внимание, что у вас может быть матрица символов;вам не нужно просто иметь числовые данные для построения матрицы в R.

При преобразовании фрейма данных в матрицу обратите внимание, что есть функция data.matrix(), которая соответствующим образом обрабатывает факторы, преобразовывая их вчисловые значения, основанные на внутренних уровнях.Приведение с помощью as.matrix() приведет к матрице символов, если любая из меток фактора не является числовой.Сравните:

> head(as.matrix(data.frame(a = factor(letters), B = factor(LETTERS))))
     a   B  
[1,] "a" "A"
[2,] "b" "B"
[3,] "c" "C"
[4,] "d" "D"
[5,] "e" "E"
[6,] "f" "F"
> head(data.matrix(data.frame(a = factor(letters), B = factor(LETTERS))))
     a B
[1,] 1 1
[2,] 2 2
[3,] 3 3
[4,] 4 4
[5,] 5 5
[6,] 6 6

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

46 голосов
/ 02 февраля 2012

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

m <- matrix(1:400000, 200000, 2)
d <- data.frame(m)
object.size(m)
# 1600200 bytes
object.size(d)
# 1600776 bytes

... если у вас нет большого количества столбцов:

m <- matrix(1:400000, 2, 200000)
d <- data.frame(m)
object.size(m)
# 1600200 bytes
object.size(d)
# 22400568 bytes
9 голосов
/ 02 марта 2011

Матрица на самом деле является вектором с дополнительными методами.пока data.frame - это список.Разница заключается в том, чтобы вектор против списка.для эффективности вычислений придерживайтесь матрицы.Использование data.frame, если вам нужно.

0 голосов
/ 25 октября 2018

Я не могу больше подчеркнуть разницу в эффективности между двумя! Хотя это правда, что DF более удобны в некоторых случаях анализа данных, они также допускают разнородные данные, и некоторые библиотеки принимают их только, но все это на самом деле вторично, если вы не пишете одноразовый код для конкретной задачи.

Позвольте привести пример. Была функция, которая вычисляла бы 2D путь метода MCMC. По сути, это означает, что мы берем начальную точку (x, y) и повторяем определенный алгоритм, чтобы найти новую точку (x, y) на каждом шаге, таким образом создавая весь путь. Алгоритм включает в себя вычисление довольно сложной функции и генерацию некоторой случайной величины на каждой итерации, поэтому, когда она запускалась в течение 12 секунд, я думала, что это нормально, учитывая, сколько вещей она делает на каждом шаге. При этом функция собрала все точки в построенном пути вместе со значением целевой функции в data-frame из трех столбцов. Таким образом, 3 столбца не так велики, и число шагов также было более чем разумным 10000 (в этом типе проблем типичны пути длиной 1 000 000, поэтому 10 000 - это ничто). Итак, я думал, что DF 10,000x3 определенно не проблема. Причина использования DF проста. После вызова функции был вызван ggplot (), чтобы нарисовать результирующий (x, y) -path. И ggplot () не принимает матрицу.

Затем в какой-то момент из любопытства я решил изменить функцию, чтобы собирать путь в матрице. Радостно, что синтаксис DF и матриц похож, все, что я сделал, это изменил строку, указав df как data.frame, на строку, инициализировав ее как матрицу. Здесь я также должен упомянуть, что в исходном коде DF был инициализирован, чтобы иметь окончательный размер, поэтому позже в коде функции только новые значения были записаны в уже выделенные пробелы, и не было никаких дополнительных затрат на добавление новых строк в DF. Это делает сравнение еще более справедливым, а также упрощает мою работу, поскольку мне не нужно было ничего переписывать в функции. Изменение только одной строки от первоначального размещения data.frame требуемого размера на матрицу того же размера. Чтобы адаптировать новую версию функции к ggplot (), я преобразовал теперь возвращенную матрицу в data.frame для использования в ggplot ().

После повторного запуска кода я не мог поверить в результат. Код запускается за доли секунды! Вместо примерно 12 секунд. И снова, функция в течение 10 000 итераций считывает и записывает значения только в уже выделенные пространства в DF (а теперь и в матрице). И эта разница также для разумного (или, скорее, небольшого) размера 10000x3.

Итак, если ваша единственная причина использовать DF - сделать его совместимым с библиотечной функцией, такой как ggplot (), вы всегда можете преобразовать его в DF в последний момент - работать с матрицами настолько, насколько вам кажется удобный. Если, с другой стороны, есть более существенная причина для использования DF, например, вы используете какой-то пакет анализа данных, который в противном случае потребовал бы постоянного преобразования из матриц в DF и обратно, или вы не выполняете интенсивные вычисления самостоятельно и используете только стандартные пакеты (многие из них на самом деле внутренне преобразуют DF в матрицу, выполняют свою работу, а затем преобразуют результат обратно - так, что они выполняют всю эффективную работу за вас), или выполняют разовую работу, чтобы вам было все равно удобнее с DF, тогда вам не стоит беспокоиться об эффективности.

Или другое, более практичное правило: если у вас есть вопрос, такой как в OP, используйте матрицы, чтобы вы использовали DF только тогда, когда у вас нет такого вопроса (поскольку вы уже знаете, что должны использовать DF, или потому что вам на самом деле все равно, так как код разовый и т. д.).

Но в целом всегда помните об этой точке эффективности как о приоритетной.

0 голосов
/ 10 декабря 2017

Матрицы и фреймы данных представляют собой прямоугольные двумерные массивы и могут быть неоднородно по строкам и столбцам . Они делятся некоторыми методами и свойства, но не все.

Примеры:

M <- list(3.14,TRUE,5L,c(2,3,5),"dog",1i)  # a list
dim(M) <- c(2,3)                           # set dimensions
print(M)                                   # print result

#      [,1]  [,2]      [,3]
# [1,] 3.14  5         "dog"
# [2,] TRUE  Numeric,3 0+1i

DF <- data.frame(M)                   # a data frame
print(DF)                             # print result

#      X1      X2   X3
#  1 3.14       5  dog
#  2 TRUE 2, 3, 5 0+1i

M <- matrix(c(1,1,1,1,2,3,1,3,6),3)   # a numeric matrix
DF <- data.frame(M)                   # a all numeric data frame

solve(M)                              # obtains inverse matrix
solve(DF)                             # obtains inverse matrix
det(M)                                # obtains determinant
det(DF)                               # error
...