Создайте фрейм данных неравной длины - PullRequest
19 голосов
/ 25 августа 2011

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

x = c(rep("one",2))
y = c(rep("two",10))
z = c(rep("three",5))
cbind(x,y,z)

В приведенном выше коде функция cbind() просто перезаписывает более короткие столбцы, чтобы в каждом из них было по 10 элементов. Как я могу изменить это так, чтобы длины были 2, 10 и 5.

Я делал это в прошлом, выполняя следующее, но это неэффективно.

  df = data.frame(one=c(rep("one",2),rep("",8)), 
           two=c(rep("two",10)), three=c(rep("three",5), rep("",5))) 

Ответы [ 5 ]

26 голосов
/ 26 августа 2011

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

Во-первых, если векторы имеют разную длину, данные на самом деле не являются табличными, не так ли? Как насчет просто сохранить его в разные файлы CSV? Вы можете также попробовать форматы ascii, которые позволяют хранить несколько объектов ( json , XML ).

Если вы чувствуете, что данные действительно являются табличными, вы можете добавить в NA:

> x = 1:5
> y = 1:12
> max.len = max(length(x), length(y))
> x = c(x, rep(NA, max.len - length(x)))
> y = c(y, rep(NA, max.len - length(y)))
> x
 [1]  1  2  3  4  5 NA NA NA NA NA NA NA
> y
 [1]  1  2  3  4  5  6  7  8  9 10 11 12

Если вам абсолютно необходимо сделать data.frame с неравными столбцами, вы можете подорвать чек на свой страх и риск:

> x = 1:5
> y = 1:12
> df = list(x=x, y=y)
> attributes(df) = list(names = names(df),
    row.names=1:max(length(x), length(y)), class='data.frame')
> df
      x  y
1     1  1
2     2  2
3     3  3
4     4  4
5     5  5
6  <NA>  6
7  <NA>  7
 [ reached getOption("max.print") -- omitted 5 rows ]]
Warning message:
In format.data.frame(x, digits = digits, na.encode = FALSE) :
  corrupt data frame: columns will be truncated or padded with NAs
6 голосов
/ 26 августа 2011

Еще один подход к заполнению:

na.pad <- function(x,len){
    x[1:len]
}

makePaddedDataFrame <- function(l,...){
    maxlen <- max(sapply(l,length))
    data.frame(lapply(l,na.pad,len=maxlen),...)
}

x = c(rep("one",2))
y = c(rep("two",10))
z = c(rep("three",5))

makePaddedDataFrame(list(x=x,y=y,z=z))

Функция na.pad() использует тот факт, что R автоматически дополнит вектор NA, если вы попытаетесь проиндексировать несуществующие элементы.

makePaddedDataFrame() просто находит самый длинный и дополняет остальные до соответствующей длины.

5 голосов
/ 26 августа 2011

Чтобы усилить ответ @ goodside, вы можете сделать что-то вроде

L <- list(x,y,z)
cfun <- function(L) {
  pad.na <- function(x,len) {
   c(x,rep(NA,len-length(x)))
  }
  maxlen <- max(sapply(L,length))
  do.call(data.frame,lapply(L,pad.na,len=maxlen))
}

(не проверено).

3 голосов
/ 26 августа 2011

Это невозможно.Самое близкое, что вы можете получить, это заполнить «пустые» пробелы значением NA.

0 голосов
/ 19 сентября 2017

Аналогичная проблема:

 coin <- c("Head", "Tail")
toss <- sample(coin, 50, replace=TRUE)

categorize <- function(x,len){
  count_heads <- 0
  count_tails <- 0
  tails <- as.character()
  heads <- as.character()
  for(i in 1:len){
    if(x[i] == "Head"){
      heads <- c(heads,x[i])
      count_heads <- count_heads + 1
    }else {
      tails <- c(tails,x[i])
      count_tails <- count_tails + 1
    }
  }
  if(count_heads > count_tails){
    head <- heads
    tail <- c(tails, rep(NA, (count_heads-count_tails)))
  } else {
    head <- c(heads, rep(NA,(count_tails-count_heads)))
    tail <- tails
  }
  data.frame(cbind("Heads"=head, "Tails"=tail))
}

классифицировать (бросить, 50)

Вывод: После броска монеты будет 31 Голова и19 Хвост.Затем оставшаяся часть хвоста будет заполнена символом NA, чтобы создать фрейм данных.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...