2015-12-30 7 views
-3

У меня есть вектор строк, которые я хочу использовать в качестве заголовков столбцов для фрейма данных.Попытка динамического создания кадра данных в R

Пример: cols < - c ("A: Ike (N = 428)", "F: Mike (N = 691)", "G: велосипед (N = 380)", "Всего (N = 1499) "," p value ")

У меня есть список списков строк, которые я хочу добавить в качестве данных из моего фрейма данных.

Пример, 1-три ряда:

[[1]] [[1]]$Female [[1]]$Female[[1]] [1] "151" "35.3%" 

[[1]]$`Age in Years` [[1]]$`Age in Years`[[1]] NULL 

[[1]]$`Mean (SD)` [[1]]$`Mean (SD)`[[1]] [1] "59.7" "11.4" 

[[2]] [[2]]$Female [[2]]$Female[[1]] [1] "280" "40.5%" 

[[2]]$`Age in Years` [[2]]$`Age in Years`[[1]] NULL 

[[2]]$`Mean (SD)` [[2]]$`Mean (SD)`[[1]] [1] "60.3" "11.6" 

[[3]] [[3]]$Female [[3]]$Female[[1]] [1] "152" "40%" 

[[3]]$`Age in Years` [[3]]$`Age in Years`[[1]] NULL 

[[3]]$`Mean (SD)` [[3]]$`Mean (SD)`[[1]] [1] "59.8" "11.5" 

[[4]] [[4]]$Female [[4]]$Female[[1]] [1] "583" "38.9%" 

[[4]]$`Age in Years` [[4]]$`Age in Years`[[1]] NULL 

[[4]]$`Mean (SD)` [[4]]$`Mean (SD)`[[1]] [1] "60" "11.5" 

[[5]] [[5]]$Female [[5]]$Female[[1]] [1] "0.190" 

[[5]]$`Age in Years` [[5]]$`Age in Years`[[1]] [1] "0.614" 

IOW, я хочу кадр данных, где столбец 1 называются именами [1] и состоит из frameLists [[1]].

Per ниже предложения, я изменил код на следующее:

outFrame <- do.call(data.frame, c(frameLists, stringsAsFactors = FALSE)) 
colnames(outFrame) <- cols 

Результаты приходят обратно глядя, как это:

A: Ike (N=428) F: Mike (N=691) G: Bike (N=380) Total (N=1499) p value NA  NA NA NA NA 
1   151   59.7    280   60.3  152 59.8 583 60 0.190 0.614 
2   35.3%   11.4   40.5%   11.6  40% 1.5 38.9% 11.5 0.190 0.614 

Результаты Я хочу:

A: Ike (N=428) F: Mike (N=691) G: Bike (N=380) Total (N=1499) p value 
1  151, 35.3%  280, 40.5%  152, 40%  583, 38.9% 0.190 
2                 0.614 
3  59.7, 11.4  60.3, 11.6  59.8, 11.5  60, 11.5   
+0

Что такое 'names'? пожалуйста, опубликуйте вывод имен – MaxPD

+1

. На самом деле вы пытаетесь создать столбец динамически, а не фреймворк данных. Есть ли в framefists frameframe столбцы с именем «1»? Попробуйте frameLists [который] с одиночной квадратной скобкой. – MaxPD

+2

'names' и' which' являются функциями R. Старайтесь избегать использования имен функций в качестве имен объектов, это запутывает. – marbel

ответ

0

Построено следующее, чтобы удовлетворить мои потребности. Это неуклюже, но пока это работает. Во-первых: выход:

> myDF 
      A: Ike (N=428) F: Mike (N=691) G: Bike (N=380) Total (N=1499) p value 
Female   151, 35.3%  280, 40.5%  152, 40%  583, 38.9% 0.190 
Age in Years                 0.614 
Mean (SD)  59.7, 11.4  60.3, 11.6  59.8, 11.5  60, 11.5   
Q1, Q3    53, 68   52, 69   52, 68   52, 68   
Range    27, 88   19, 88   26, 85   19, 88   

Теперь код, который генерируется его:

#' Make a data.frame given the column headers and data to fill the data.frame 
#' 
#' @param cols   Vector of text holding the column names 
#' @param frameLists List of lists holding the data for the data frame. First list element 
#' must have all the names used in frameLists. Must be as many lists in frameLists as there are 
#' Strings in cols 
#' @returnType Data Frame 
#' @return Data Frame with all the elements set up and filled in 
buildFrame <- function (cols, frameLists) { 
    outList <- list() 
    for (col in cols) { 
     outList[[col]] <- NA 
    } 

    outFrame = data.frame(outList, stringsAsFactors = FALSE) 
    colnames(outFrame) <- cols 

    outList <- list() 
    for (col in cols) { 
     outList[[col]] <- list() 
    } 

    theNames <- names(frameLists[[1]]) 
    whichCol <- 1 
    for (topList in frameLists) { 
     colList <- outList[[whichCol]] 
     for (aName in theNames) { 
      data <- topList[[aName]] 
      if (is.null(data)) { 
       colList[[aName]] <- "" 
      } 
      else { 
       colList[[aName]] <- data 
      } 
     } 
     outList[[whichCol]] <- colList 
     whichCol <- whichCol + 1 
    } 

    outFrame <- rbind(outList, outFrame) 
    outFrame <- outFrame[-1 - length(theNames), ] 
    rownames(outFrame) <- theNames 

    return(outFrame) 
} 
2

Предполагая, что все списки имеют одинаковое количество строк внутри, попробуйте

result <- do.call(data.frame, c(lapply(frameLists, unlist), stringsAsFactors=F)) 
names(result) <- name 

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

frameLists <- list(list(c("asd", "faf"), NULL, c("3", "2")), list(c("aaa", "zzz"),NULL, c("1", "3")), list(c("qw", "gs"), NULL, c("3", "2"))) 
name <- c("a", "b", "c") 

Выход

> result 
    a b c 
1 asd aaa qw 
2 faf zzz gs 
3 3 1 3 
4 2 3 2 
> str(result) 
'data.frame': 4 obs. of 3 variables: 
$ a: chr "asd" "faf" "3" "2" 
$ b: chr "aaa" "zzz" "1" "3" 
$ c: chr "qw" "gs" "3" "2" 

Другая возможная интерпретация (не уверены, какой вы хотите) того же ввода:

res <- as.data.frame(do.call(cbind, lapply(frameLists, function(x) do.call(cbind, x))), stringsAsFactors=F) 

Выход

> res 
    V1 V2 V3 V4 V5 V6 
1 asd 3 aaa 1 qw 3 
2 faf 2 zzz 3 gs 2 
> str(res) 
'data.frame': 2 obs. of 6 variables: 
$ V1: chr "asd" "faf" 
$ V2: chr "3" "2" 
$ V3: chr "aaa" "zzz" 
$ V4: chr "1" "3" 
$ V5: chr "qw" "gs" 
$ V6: chr "3" "2" 
+0

На самом деле это не работает. do.call настаивает на распаде всех моих данных. Даже если я сделаю список списков списков (а не векторов), каждая строка отправится в свой собственный столбец –

+0

, поэтому я проиллюстрировал, как я создал свои данные, потому что я не уверен, как ваша структура данных. «Список списков» был расплывчатым. Можете ли вы 'dput' ваш текущий список списков, чтобы я мог адаптировать решение? – Ricky

+0

также каков ваш желаемый результат? Кажется, у вас есть только текущий выход. Я не знаю, например. как вы хотите рассматривать NULL в списке. – Ricky

2

Ваш код не работает, потому что вы инициализирован results как пустой кадр данных, который R требуется, чтобы быть кадр данных с 0 строк и столбцов 0. При добавлении столбца в фрейм данных его количество строк должно соответствовать существующему фрейму. Вот почему вы получили сообщение об ошибке replacement has 2 rows, data has 0.

Было бы проще связать список столбцов вместе в dataframe все сразу. Проблема в том, что функция data.frame не хочет список, она хочет, чтобы каждый столбец был отдельным аргументом:

data.frame(c(1,2,3),c(4,5,6),c(34,1,1)).

Как вы можете сделать data.frame взять список столбцов, а не несколько аргументов?

Это то, что do.call предназначено для!

Дает do.call функцию и список аргументов, и он обрабатывает аргументы функции по одному.

colList <- list(c(1,2,3),c(4,5,6),c(34,1,1)) 
col_names <- c('a','b','c') 
df <- do.call(data.frame,colList) 
colnames(df) <- col_names 

Результат:

> df 
    a b c 
1 1 4 34 
2 2 5 1 
3 3 6 1 

одинаково хорошо работает, если colList список векторов строк, но вы можете использовать stringsAsFactors = F, чтобы избежать преобразования коэффициента по data.frame.

+0

. Вы получите зеленый чек для объяснения do.call. Спасибо! –

+0

На самом деле это не работает. do.call настаивает на распаде всех моих данных. Даже если я сделаю список списков списков (а не векторов), каждая строка перейдет в свой собственный столбец –

+0

Ваша структура данных выглядит намного сложнее, чем может обрабатывать этот код (откровенно сложный). Это беспорядок, показанный на вашем посте, распечаткой R? Я до сих пор не могу сказать, что такое структура данных. Я думаю, что это может быть отсутствие некоторых возвратов каретки. – Paul