Типы переменных R изменяются после транспонирования фрейма данных

Меня всегда смущали типы переменных в R. Теперь я столкнулся с проблемой после переноса фрейма данных.

Например, я использую table() для подсчета каждого фактора в определенном векторе:

data(iris)

count <- as.data.frame(table(iris$Species))
typeof(count$Var1)
# [1] "integer"

typeof(count$Freq)
# [1] "integer"

Мой первый вопрос: почему count$Var1 "целое число"? Могут ли строки быть "целыми" тоже? Но это не имеет значения, потому что я могу изменить тип на count$Var1 <- as.character(count$Var1), тогда typeof(count$Var1) станет "символом".

Теперь я транспонирую этот фрейм данных на transposed_count <- as.data.frame(t(count)). Но я запутался, потому что:

typeof(transposed_count[1,])
[1] "list"

typeof(transposed_count[2,])
[1] "list"

transposed_count[2,]
     V1 V2 V3
Freq 50 50 50

Для последующего использования мне нужно, чтобы transposed_count[2,] был числовым вектором, например:

transposed_count[2,]
[1] 50 50 50

Как я могу это сделать? И почему они стали "списком" после t()? Извините, если это глупый вопрос. Спасибо!


person Yan    schedule 15.02.2017    source источник


Ответы (3)


Мой первый вопрос: почему count$Var1 "целое число"?

Поскольку факторы имеют целочисленный тип хранения

> is.factor(count$Var1)
[1] TRUE

а «струны» в радужной оболочке data.frame, как это обычно бывает в R, сохраняются как множители.

И почему они стали "списком" после t()?

Когда вы транспонируете, вы получаете матрицу, а матрицы должны иметь один и тот же класс хранения для каждой записи. То, что вы на самом деле получите первым, — это матрица символов, так как целые значения будут принудительно заданы. Затем, когда вы впоследствии перейдете на data.frame, эти символы по умолчанию будут заменены (новыми) множителями.

> t(count)
     [,1]     [,2]         [,3]       
Var1 "setosa" "versicolor" "virginica"
Freq "50"     "50"         "50" 

> transposed_count <- as.data.frame(t(count))

> transposed_count[2,1]
Freq 
  50 
Levels: 50 setosa
> as.numeric(transposed_count[2,1])
[1] 1

Итак, то, что было числом 50, теперь является фактором с числовым значением 1! Не то, что вы хотите.

Почему typeof(transposed_count[1,]) — это список? Горизонтальный срез data.frame на самом деле является data.frame.

> is.data.frame(transposed_count[2,])
[1] TRUE

А data.frames — это просто списки с информацией о классе.

Но как тогда я могу получить «транспонированный» фрейм данных?

Похоже, вы хотите

> library(reshape2)
> dcast(melt(count), variable~Var1)
Using Var1 as id variables
  variable setosa versicolor virginica
1     Freq     50         50        50

после того, как я прочитаю все образцы, я собираюсь связать все кадры данных

Вы должны убедиться, что столбцы выровнены надлежащим образом. В зависимости от предстоящего анализа может быть более естественным использовать rbind, как и другой столбец, указывающий источник.

> count2 <- count
> count$source = "file1"
> count2$source = "file2"
> (mcount <- rbind(count,count2))
        Var1 Freq source
1     setosa   50  file1
2 versicolor   50  file1
3  virginica   50  file1
4     setosa   50  file2
5 versicolor   50  file2
6  virginica   50  file2

Теперь вам не нужно беспокоиться о выравнивании, если вы хотите изменить форму позже

> dcast(melt(mcount), ...~Var1)
Using Var1, source as id variables
  source variable setosa versicolor virginica
1  file1     Freq     50         50        50
2  file2     Freq     50         50        50
person A. Webb    schedule 15.02.2017
comment
Спасибо за объяснение! Мне стало понятнее. Но как тогда я могу получить транспонированный фрейм данных? - person Yan; 15.02.2017
comment
Я читаю кучу файлов, каждый файл как каждый образец. Наконец, мне нужен фрейм данных, в котором строки являются выборками, а столбцы - количеством каждого элемента в каждом файле/выборке. Итак, после того, как я прочитаю все образцы, я собираюсь связать все кадры данных. Вот почему мне нужно, чтобы это было транспонировано. Я собираюсь поставить Var1 в качестве столбцов для окончательного фрейма данных. - person Yan; 15.02.2017
comment
Как предположил @Roman Luštrik, вы, вероятно, ищете что-то вроде dcast(melt(count), ...~Var1) из библиотеки reshape2. Однако, в зависимости от предстоящего анализа, более естественной формой может быть rbind данные в исходном формате с добавлением еще одного столбца с индикатором файла/образца. Это даст вам сложенный формат. - person A. Webb; 15.02.2017
comment
Большое спасибо! Теперь я знаю, что есть разница. Когда я искал транспонирование фрейма данных, t() был единственным ответом, который я получил. Но на самом деле я не должен использовать его для своей цели. - person Yan; 15.02.2017

typeof расскажет вам, как R хранит данные внутри. Для факторов это целое число. И Var1 является фактором, понимаете?

> class(count$Var1)
[1] "factor"

transposed_counts в данном случае не имеет смысла. Транспонируя, вы разрушаете логику data.frame. Транспонирование обычно имеет смысл для матриц. Если вы хотите «переформатировать» data.frame, вы можете использовать что-то вроде reshape или любого из его родственников.

person Roman Luštrik    schedule 15.02.2017
comment
Спасибо за ответ! - person Yan; 15.02.2017

Если вы сделаете имена видов в Var1 в именах строк перед транспонированием, вы избежите проблем с транспонированием, преобразующим все в один и тот же тип данных.

data(iris)
count <- as.data.frame(table(iris$Species))
row.names(count) <- count$Var1
count$Var1 <- NULL
transposed_count <- as.data.frame(t(count))
as.numeric(transposed_count[1,])
# [1] 50 50 50
person tjjjohnson    schedule 15.02.2017