Подтвердить что ты не робот

Создание кадра данных с неравными длинами

В то время как столбцы фрейма данных должны иметь одинаковые строки чисел, есть ли способ создать кадр данных с неравными длинами. Мне не интересно сохранять их в виде отдельных элементов списка, потому что мне часто приходится отправлять людям эту информацию в виде файла 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))) 
4b9b3361

Ответ 1

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

Во-первых, если векторы различной длины, данные на самом деле не являются табличными, не так ли? Как просто сохранить его в разные файлы 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

Ответ 2

Другой подход к заполнению:

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() просто находит самый длинный и подставляет остальную часть до соответствующей длины.

Ответ 3

Чтобы усилить ответ @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))
}

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

Ответ 4

Это невозможно. Ближе всего вы можете заполнить "пустые" пробелы значением NA.

Ответ 5

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

 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))
}

Categorize (бросок, 50)

Вывод: После броска монеты будет 31 Head and 19 Tail. Затем остальная часть хвоста будет заполнена NA, чтобы создать кадр данных.