cbind dataframe с пустым dataframe - cbind.fill?
Я думаю, что я ищу аналог rbind.fill
(в пакете Hadley plyr
) для cbind
. Я посмотрел, но нет cbind.fill
.
Я хочу сделать следующее:
#set these just for this example
one_option <- TRUE
diff_option <- TRUE
return_df <- data.frame()
if (one_option) {
#do a bunch of calculations, produce a data.frame, for simplicity the following small_df
small_df <- data.frame(a=1, b=2)
return_df <- cbind(return_df,small_df)
}
if (diff_option) {
#do a bunch of calculations, produce a data.frame, for simplicity the following small2_df
small2_df <- data.frame(l="hi there", m=44)
return_df <- cbind(return_df,small2_df)
}
return_df
Понятно, что это вызывает ошибку:
Error in data.frame(..., check.names = FALSE) :
arguments imply differing number of rows: 0, 1
Мое текущее исправление заключается в замене строки return_df <- data.frame()
на return_df <- data.frame(dummy=1)
, а затем код работает. Затем я просто удаляю фиктивный элемент из return_df
в конце. После добавления манекена и выполнения вышеуказанного кода я получаю
dummy a b l m
1 1 1 2 hi there 44
Мне просто нужно избавиться от манекена, например:
> return_df[,2:ncol(return_df)]
a b l m
1 1 2 hi there 44
Я уверен, что мне не хватает более простого способа сделать это.
edit: Я думаю, что я не ищу cbind.fill, потому что это означало бы, что значение NA будет создано после cbind, чего я не хочу.
Ответы
Ответ 1
Здесь cbind fill:
cbind.fill <- function(...){
nm <- list(...)
nm <- lapply(nm, as.matrix)
n <- max(sapply(nm, nrow))
do.call(cbind, lapply(nm, function (x)
rbind(x, matrix(, n-nrow(x), ncol(x)))))
}
Попробуйте:
x<-matrix(1:10,5,2)
y<-matrix(1:16, 4,4)
z<-matrix(1:12, 2,6)
cbind.fill(x,y)
cbind.fill(x,y,z)
cbind.fill(mtcars, mtcars[1:10,])
Я думаю, что я украл это откуда-то.
ИЗМЕНИТЬ СТОЛ ИЗ ЗДЕСЬ: ССЫЛКА
Ответ 2
Хотя, думаю, решение Tyler прямое и лучшее здесь, я просто предоставляю другой способ, используя rbind.fill()
, который у нас уже есть.
require(plyr) # requires plyr for rbind.fill()
cbind.fill <- function(...) {
transpoted <- lapply(list(...),t)
transpoted_dataframe <- lapply(transpoted, as.data.frame)
return (data.frame(t(rbind.fill(transpoted_dataframe))))
}
Ответ 3
Использование rowr::cbind.fill
rowr::cbind.fill(df1,df2,fill = NA)
A B
1 1 1
2 2 2
3 3 3
4 4 4
5 5 5
6 NA 6
Ответ 4
cbind.na из пакета qpcR может это сделать.
install.packages("qpcR")
library(qpcR)
qpcR:::cbind.na(1, 1:7)
Ответ 5
Я предлагаю модификацию ответа Тайлера. Моя функция позволяет cbind
-используть data.frames и/или матрицы с векторами без потери имен столбцов, как это происходит в решении Tyler
cbind.fill <- function(...){
nm <- list(...)
dfdetect <- grepl("data.frame|matrix", unlist(lapply(nm, function(cl) paste(class(cl), collapse = " ") )))
# first cbind vectors together
vec <- data.frame(nm[!dfdetect])
n <- max(sapply(nm[dfdetect], nrow))
vec <- data.frame(lapply(vec, function(x) rep(x, n)))
if (nrow(vec) > 0) nm <- c(nm[dfdetect], list(vec))
nm <- lapply(nm, as.data.frame)
do.call(cbind, lapply(nm, function (df1)
rbind(df1, as.data.frame(matrix(NA, ncol = ncol(df1), nrow = n-nrow(df1), dimnames = list(NULL, names(df1))))) ))
}
cbind.fill(data.frame(idx = numeric()), matrix(0, ncol = 2),
data.frame(qwe = 1:3, rty = letters[1:3]), type = "GOOD", mark = "K-5")
# idx V1 V2 qwe rty type mark
# 1 NA 0 0 1 a GOOD K-5
# 2 NA NA NA 2 b GOOD K-5
# 3 NA NA NA 3 c GOOD K-5
Ответ 6
Я просто нашел трюк, что, когда мы хотим добавить столбцы в пустой фреймворк, просто rbind в первый раз, чем cbind позже.
newdf <- data.frame()
# add the first column
newdf <- rbind(newdf,data.frame("col1"=c("row1"=1,"row2"=2)))
# add the second column
newdf <- cbind(newdf,data.frame("col2"=c("row1"=3,"row2"=4)))
# add more columns
newdf <- cbind(newdf,data.frame("col3"=c("row1"=5,"row2"=6)))
# result
# col1 col2 col3
#row1 1 3 5
#row2 2 4 6
Я не знаю почему, но он работает для меня.
Ответ 7
Мы могли бы добавить столбец id, а затем использовать слияние:
df1 <- mtcars[1:5, 1:2]
# mpg cyl id
# Mazda RX4 21.0 6 1
# Mazda RX4 Wag 21.0 6 2
# Datsun 710 22.8 4 3
# Hornet 4 Drive 21.4 6 4
# Hornet Sportabout 18.7 8 5
df2 <- mtcars[6:7, 3:4]
# disp hp
# Valiant 225 105
# Duster 360 360 245
#Add id column then merge
df1$id <- seq(nrow(df1))
df2$id <- seq(nrow(df2))
merge(df1, df2, by = "id", all.x = TRUE, check.names = FALSE)
# id mpg cyl disp hp
# 1 1 21.0 6 225 105
# 2 2 21.0 6 360 245
# 3 3 22.8 4 NA NA
# 4 4 21.4 6 NA NA
# 5 5 18.7 8 NA NA