I'm mencoba untuk menginisialisasi data.frame tanpa baris. Pada dasarnya, saya ingin menentukan tipe data untuk setiap kolom dan nama mereka, tetapi tidak memiliki baris yang dibuat sebagai hasil.
Terbaik I've telah mampu lakukan sejauh ini adalah sesuatu seperti:
df <- data.frame(Date=as.Date("01/01/2000", format="%m/%d/%Y"),
File="", User="", stringsAsFactors=FALSE)
df <- df[-1,]
Yang menciptakan data.bingkai dengan satu baris yang berisi semua tipe data dan nama-nama kolom yang saya inginkan, tetapi juga menciptakan berguna baris yang kemudian perlu dihapus.
Apakah ada cara yang lebih baik untuk melakukan hal ini?
Hanya menginisialisasi dengan kosong vektor:
df <- data.frame(Date=as.Date(character()),
File=character(),
User=character(),
stringsAsFactors=FALSE)
Berikut ini's sebuah contoh lain yang berbeda dengan kolom jenis :
df <- data.frame(Doubles=double(),
Ints=integer(),
Factors=factor(),
Logicals=logical(),
Characters=character(),
stringsAsFactors=FALSE)
str(df)
> str(df)
'data.frame': 0 obs. of 5 variables:
$ Doubles : num
$ Ints : int
$ Factors : Factor w/ 0 levels:
$ Logicals : logi
$ Characters: chr
N. B. :
Inisialisasi data.framedengan kolom kosong dari jenis yang salah tidak mencegah penambahan baris yang memiliki kolom yang berbeda jenis. Metode ini hanya sedikit *lebih aman* dalam arti bahwa anda'll memiliki kolom yang benar dari awal, oleh karena itu jika kode anda bergantung pada beberapa kolom jenis pemeriksaan, ia akan bekerja bahkan dengan
data.frame` dengan nol baris.
Jika anda sudah ada data frame, let's mengatakan df
yang memiliki kolom yang anda inginkan, maka anda hanya dapat membuat kosong data frame dengan menghapus semua baris:
empty_df = df[FALSE,]
Perhatikan bahwa df
masih berisi data, tapi empty_df
doesn't.
Saya menemukan pertanyaan ini mencari cara untuk membuat sebuah instance baru dengan baris kosong, jadi saya pikir ini mungkin berguna untuk beberapa orang.
Anda bisa menggunakan baca.meja
dengan string kosong untuk input teks
sebagai berikut:
colClasses = c("Date", "character", "character")
col.names = c("Date", "File", "User")
df <- read.table(text = "",
colClasses = colClasses,
col.names = col.names)
Atau menentukan col.nama
sebagai string:
df <- read.csv(text="Date,File,User", colClasses = colClasses)
Terima kasih kepada Richard Scriven untuk perbaikan
Cara yang paling efisien untuk melakukan ini adalah dengan menggunakan struktur
untuk membuat daftar yang memiliki kelas "data.frame"
:
structure(list(Date = as.Date(character()), File = character(), User = character()),
class = "data.frame")
# [1] Date File User
# <0 rows> (or 0-length row.names)
Untuk menempatkan ini dalam perspektif dibandingkan dengan saat ini jawaban yang diterima, di sini's patokan sederhana:
s <- function() structure(list(Date = as.Date(character()),
File = character(),
User = character()),
class = "data.frame")
d <- function() data.frame(Date = as.Date(character()),
File = character(),
User = character(),
stringsAsFactors = FALSE)
library("microbenchmark")
microbenchmark(s(), d())
# Unit: microseconds
# expr min lq mean median uq max neval
# s() 58.503 66.5860 90.7682 82.1735 101.803 469.560 100
# d() 370.644 382.5755 523.3397 420.1025 604.654 1565.711 100
Hanya menyatakan
table = data.frame()
ketika anda mencoba untuk rbind
baris pertama itu akan membuat kolom
Aku dibuat kosong data frame menggunakan kode berikut
df = data.frame(id = numeric(0), jobs = numeric(0));
dan mencoba untuk mengikat beberapa baris untuk mengisi yang sama sebagai berikut.
newrow = c(3, 4)
df <- rbind(df, newrow)
tapi itu mulai memberikan salah nama kolom sebagai berikut
X3 X4
1 3 4
Solusi untuk ini adalah untuk mengkonversi newrow untuk jenis df sebagai berikut
newrow = data.frame(id=3, jobs=4)
df <- rbind(df, newrow)
sekarang memberikan data yang benar frame ketika ditampilkan dengan nama-nama kolom sebagai berikut
id nobs
1 3 4
Jika anda ingin membuat data kosong.bingkai dengan dinamis nama (colnames dalam variabel), hal ini dapat membantu:
names <- c("v","u","w")
df <- data.frame()
for (k in names) df[[k]]<-as.numeric()
Anda dapat mengubah jenis dan juga jika anda perlu begitu. seperti:
names <- c("u", "v")
df <- data.frame()
df[[names[1]]] <- as.numeric()
df[[names[2]]] <- as.character()
Untuk membuat data kosong frame, lulus dalam jumlah baris dan kolom yang dibutuhkan ke dalam fungsi berikut:
create_empty_table <- function(num_rows, num_cols) {
frame <- data.frame(matrix(NA, nrow = num_rows, ncol = num_cols))
return(frame)
}
Untuk membuat bingkai kosong saat menentukan kelas dari masing-masing kolom, hanya melewati sebuah vektor yang diinginkan tipe data ke fungsi berikut:
create_empty_table <- function(num_rows, num_cols, type_vec) {
frame <- data.frame(matrix(NA, nrow = num_rows, ncol = num_cols))
for(i in 1:ncol(frame)) {
print(type_vec[i])
if(type_vec[i] == 'numeric') {frame[,i] <- as.numeric(df[,i])}
if(type_vec[i] == 'character') {frame[,i] <- as.character(df[,i])}
if(type_vec[i] == 'logical') {frame[,i] <- as.logical(df[,i])}
if(type_vec[i] == 'factor') {frame[,i] <- as.factor(df[,i])}
}
return(frame)
}
Penggunaan sebagai berikut:
df <- create_empty_table(3, 3, c('character','logical','numeric'))
Yang memberikan:
X1 X2 X3
1 <NA> NA NA
2 <NA> NA NA
3 <NA> NA NA
Untuk mengkonfirmasi pilihan anda, jalankan perintah berikut:
lapply(df, class)
#output
$X1
[1] "character"
$X2
[1] "logical"
$X3
[1] "numeric"
Jika anda don't pikiran tidak menentukan tipe data secara eksplisit, anda dapat melakukannya dengan cara ini:
headers<-c("Date","File","User")
df <- as.data.frame(matrix(,ncol=3,nrow=0))
names(df)<-headers
#then bind incoming data frame with col types to set data types
df<-rbind(df, new_df)
Jika anda ingin menyatakan seperti data.frame
dengan banyak kolom, it'mungkin akan menjadi rasa sakit untuk semua jenis kolom kelas dengan tangan. Terutama jika anda dapat membuat penggunaan rep
, pendekatan ini mudah dan cepat (sekitar 15% lebih cepat daripada solusi lain yang dapat digeneralisasi seperti ini):
Jika yang anda inginkan kolom kelas di sebuah vektor colClasses
, anda dapat melakukan hal-hal berikut:
library(data.table)
setnames(setDF(lapply(colClasses, function(x) eval(call(x)))), col.names)
lapply
akan menghasilkan daftar panjang yang diinginkan, masing-masing elemen yang hanya kosong yang diketik vektor seperti numerik()
atau integer()
.
setDF
mualaf ini daftar
oleh referensi untuk sebuah data.frame`.
setnames
menambahkan nama yang dikehendaki oleh referensi.
Perbandingan kecepatan:
classes <- c("character", "numeric", "factor",
"integer", "logical","raw", "complex")
NN <- 300
colClasses <- sample(classes, NN, replace = TRUE)
col.names <- paste0("V", 1:NN)
setDF(lapply(colClasses, function(x) eval(call(x))))
library(microbenchmark)
microbenchmark(times = 1000,
read = read.table(text = "", colClasses = colClasses,
col.names = col.names),
DT = setnames(setDF(lapply(colClasses, function(x)
eval(call(x)))), col.names))
# Unit: milliseconds
# expr min lq mean median uq max neval cld
# read 2.598226 2.707445 3.247340 2.747835 2.800134 22.46545 1000 b
# DT 2.257448 2.357754 2.895453 2.401408 2.453778 17.20883 1000 a
It's juga lebih cepat daripada menggunakan struktur
dalam cara yang sama:
microbenchmark(times = 1000,
DT = setnames(setDF(lapply(colClasses, function(x)
eval(call(x)))), col.names),
struct = eval(parse(text=paste0(
"structure(list(",
paste(paste0(col.names, "=",
colClasses, "()"), collapse = ","),
"), class = \"data.frame\")"))))
#Unit: milliseconds
# expr min lq mean median uq max neval cld
# DT 2.068121 2.167180 2.821868 2.211214 2.268569 143.70901 1000 a
# struct 2.613944 2.723053 3.177748 2.767746 2.831422 21.44862 1000 b
Jika anda sudah memiliki dataframe, anda dapat mengekstrak metadata (nama kolom dan tipe) dari dataframe (misalnya jika anda mengendalikan sebuah BUG yang hanya dipicu dengan masukan tertentu dan membutuhkan kosong dummy Dataframe):
`` colums_and_types <- sapply(df, kelas)
cetak(dput(sebagai.karakter(nama(colums_and_types))))
dput(sebagai.karakter(seperti.vektor(colums_and_types))) ``
Dan kemudian menggunakan baca.meja
untuk membuat kosong dataframe
baca.tabel(text = "", colClasses = c('integer', 'faktor'), col.nama = c('col1', 'col2'))
Mengucapkan nama-nama kolom yang dinamis, anda bisa membuat baris kosong-bernama matrix dan mengubahnya menjadi sebuah frame data.
nms <- sample(LETTERS,sample(1:10))
as.data.frame(t(matrix(nrow=length(nms),ncol=0,dimnames=list(nms))))
Pertanyaan ini tidak't secara khusus menangani keprihatinan saya (yang diuraikan di sini) tapi jika ada yang ingin melakukan hal ini dengan parameter jumlah kolom dan tidak ada paksaan:
> require(dplyr)
> dbNames <- c('a','b','c','d')
> emptyTableOut <-
data.frame(
character(),
matrix(integer(), ncol = 3, nrow = 0), stringsAsFactors = FALSE
) %>%
setNames(nm = c(dbNames))
> glimpse(emptyTableOut)
Observations: 0
Variables: 4
$ a <chr>
$ b <int>
$ c <int>
$ d <int>
Sebagai divibisan serikat pada linked pertanyaan,
...alasan [pemaksaan] terjadi [ketika cbinding matrik dan penyusunnya jenis] adalah matriks hanya dapat memiliki tipe data tunggal. Ketika anda cbind 2 matriks, hasilnya masih matriks dan jadi variabel adalah semua dipaksa menjadi satu jenis sebelum untuk mengkonversi data.frame