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