потеря dataframe при использовании do.call - PullRequest
5 голосов
/ 02 ноября 2011

Я пытаюсь объединить несколько фреймов данных, используя rbind.Если я вызываю rbind directy, проблем не возникает:

> test <- rbind(x)
> is.data.frame(x)
[1] TRUE

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

>test <- do.call("rbind", x)
> is.data.frame(test)
[1] FALSE

Согласно документации rbind, я попробовал add stringsAsFactors = FALSE, но без изменений в поведении.Мои таблицы данных выглядят примерно так:

ID  sequence    descriptor
1   aaacccttt   g12
2   actttgtgt   e34
3   tttgggctc   b12
4   ccgcgcgcg   c12
…   …       ...

и вывод rbind выглядит так, но вывод do.call("rbind", x) выглядит следующим образом, где столбец последовательности больше не является символом:

ID  363 426 91
Sequence 98 353 100
descriptor  g12 b12 c12 

Я хотел бы использовать do.call, потому что я циклически перебираю набор фреймов данных, чтобы объединить их с помощью приведенного ниже сценария.Другой полезный ответ может предложить альтернативное решение о том, как объединить несколько фреймов данных, вызывая их в цикле.

stringsAsFactors = FALSE
dfs <- as.list(ls(pattern="Data_"))
for (i in 1:length(dfs)) {
  x <- get(as.character(dfs[i]))
  AllData <- do.call("rbind", x) 
  }

dfs - это список фреймов данных в моей рабочей среде, и я получаю реальный фрейм данных, используя get

спасибо.

Ответы [ 3 ]

4 голосов
/ 02 ноября 2011

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

  • stringsAsFactors

Вы правы, глядя на stringsAsFactors, но просто не назвали его в нужном месте.

У вас есть два варианта. Вы можете установить его в вашем options, например так:

options(stringsAsFactors=FALSE)

Или в коде, используемом для создания data.table s:

a <- read.table(textConnection("ID  sequence    descriptor
1   aaacccttt   g12
2   actttgtgt   e34
3   tttgggctc   b12
4   ccgcgcgcg   c12"),
header=T, stringsAsFactors=FALSE)
  • args= аргумент do.call()

Вы также на правильном пути, если хотите использовать do.call() для этого. Но, как указывает @Sacha, dfs должен быть списком data.frame s, а не одним data.frame (который сам по себе является списком векторов).

# Create list of two data.frames
b <- a
dfs <- list(a, b)

# Or, if you start with a list of their names
dfs <- list("a", "b")
dfs <- lapply(dfs, get)

# Check that this works
do.call("rbind", dfs)
#   ID  sequence descriptor
# 1  1 aaacccttt        g12
# 2  2 actttgtgt        e34
# 3  3 tttgggctc        b12
# 4  4 ccgcgcgcg        c12
# 5  1 aaacccttt        g12
# 6  2 actttgtgt        e34
# 7  3 tttgggctc        b12
# 8  4 ccgcgcgcg        c12

Это также должно работать для вас, даже если у вас есть только один data.frame, если он заключен в (length-1) list, например: dfs <- list(a)

2 голосов
/ 02 ноября 2011

Используя пример кода Джоша. Я почти уверен, что происходит следующее:

Data:
    x <- read.table(textConnection("ID  sequence    descriptor
    1   aaacccttt   g12
    2   actttgtgt   e34
    3   tttgggctc   b12
    4   ccgcgcgcg   c12"),
    header=T, stringsAsFactors=FALSE)

Сначала это:

rbind(x)

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

do.call("rbind", x)

Здесь происходит то, что rbind() вызывается со всеми аргументами в списке x. Фрейм данных - это список со столбцами в качестве элементов. Следовательно, это будет так же, как:

rbind(x$ID,x$sequence,x$descriptor)

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

Я думаю, что если x - это список данных, он работает нормально. Это просто не должен быть сам фрейм данных.

1 голос
/ 02 ноября 2011

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

dfs <- as.list(ls(pattern="Data_"))
Reduce('rbind', dfs)
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...