قم بإنشاء ملف data.frame فارغ




dataframe (9)

إذا كان لديك بالفعل إطار بيانات موجود ، دعنا نقول df يحتوي على الأعمدة التي تريدها ، عندها يمكنك فقط إنشاء إطار بيانات فارغ عن طريق إزالة جميع الصفوف:

empty_df = df[FALSE,]

لاحظ أن df لا يزال يحتوي على البيانات ، لكن empty_df لا.

لقد وجدت هذا السؤال أبحث عن كيفية إنشاء مثيل جديد يحتوي على صفوف فارغة ، لذلك أعتقد أنه قد يكون مفيدًا لبعض الأشخاص.

أحاول تهيئة data.frame بدون أي صفوف. في الأساس ، أريد تحديد أنواع البيانات لكل عمود وتسميةها ، ولكن ليس لديك أي صفوف تم إنشاؤها كنتيجة.

أفضل ما استطعت القيام به حتى الآن هو شيء مثل:

df <- data.frame(Date=as.Date("01/01/2000", format="%m/%d/%Y"), 
                 File="", User="", stringsAsFactors=FALSE)
df <- df[-1,]

مما يؤدي إلى إنشاء ملف data.frame مع صف واحد يحتوي على جميع أنواع البيانات وأسماء الأعمدة التي كنت أرغب فيها ، ولكنه ينشئ أيضًا صفًا عديم الفائدة والذي يلزم إزالته بعد ذلك.

هل هناك طريقة أفضل للقيام بذلك؟


إذا كنت تبحث عن قصر:

read.csv(text="col1,col2")

لذلك لا تحتاج إلى تحديد أسماء الأعمدة بشكل منفصل. يمكنك الحصول على نوع العمود الافتراضي منطقي حتى تقوم بتعبئة إطار البيانات.


إذا كنت تريد الإعلان عن مثل هذا data.frame بالعديد من الأعمدة ، فمن المحتمل أن يكون هناك ألم لكتابة جميع فئات الأعمدة يدويًا. خاصة إذا كان بإمكانك استخدام rep ، فإن هذا الأسلوب سهل وسريع (حوالي 15٪ أسرع من الحل الآخر الذي يمكن تعميمه على هذا النحو):

إذا كانت فئات الأعمدة المرغوبة في colClasses متجهة ، فيمكنك القيام بما يلي:

library(data.table)
setnames(setDF(lapply(colClasses, function(x) eval(call(x)))), col.names)

lapply سيؤدي إلى قائمة الطول المطلوب ، كل عنصر منها هو مجرد ناقل فارغ مكتوب مثل numeric() أو integer() .

يحول setDF هذه list بالرجوع إلى data.frame .

يضيف setnames الأسماء المطلوبة حسب المرجع.

مقارنة السرعة:

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 

كما أنه أسرع من استخدام structure بطريقة مشابهة:

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

إذا كنت لا تمانع في عدم تحديد أنواع البيانات بشكل صريح ، فيمكنك القيام بذلك على النحو التالي:

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)

فقط قم بالإعلان عن table = data.frame () عند محاولة إعادة سطر السطر الأول سيقوم بإنشاء الأعمدة


لقد أنشأت إطارًا فارغًا للبيانات باستخدام التعليمة البرمجية التالية

df = data.frame(id = numeric(0), jobs = numeric(0));

وحاول لربط بعض الصفوف لتعبئة نفسه على النحو التالي.

newrow = c(3, 4)
df <- rbind(df, newrow)

لكنها بدأت تعطي أسماء الأعمدة غير صحيحة كما يلي

  X3 X4
1  3  4

الحل إلى هذا هو تحويل newrow إلى كتابة df كما يلي

newrow = data.frame(id=3, jobs=4)
df <- rbind(df, newrow)

الآن يعطي إطار البيانات الصحيح عند عرضها مع أسماء الأعمدة على النحو التالي

  id nobs
1  3   4 

مجرد تهيئته مع ناقلات فارغة:

df <- data.frame(Date=as.Date(character()),
                 File=character(), 
                 User=character(), 
                 stringsAsFactors=FALSE) 

فيما يلي مثال آخر بنوع مختلف من الأعمدة:

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 

ملحوظة:

لا تعمل تهيئة data.frame مع عمود فارغ من النوع غير data.frame على منع الإضافات الإضافية للصفوف التي لها أعمدة من أنواع مختلفة.
هذه الطريقة أكثر أمانًا قليلاً بمعنى أنه سيكون لديك أنواع الأعمدة الصحيحة من البداية ، ومن ثم إذا كانت شفرتك تعتمد على بعض التحقق من نوع العمود ، data.frame حتى مع data.frame مع الصفوف الصفرية.


يمكنك استخدام read.table بسلسلة فارغة text الإدخال كما يلي:

colClasses = c("Date", "character", "character")
col.names = c("Date", "File", "User")

df <- read.table(text = "",
                 colClasses = colClasses,
                 col.names = col.names)

بدلا من ذلك تحديد col.names كسلسلة:

df <- read.csv(text="Date,File,User", colClasses = colClasses)

شكرا لريتشارد سكريفن للتحسين


لإنشاء إطار بيانات فارغ ، قم بتمرير عدد الصفوف والأعمدة المطلوبة إلى الوظيفة التالية:

create_empty_table <- function(num_rows, num_cols) {
    frame <- data.frame(matrix(NA, nrow = num_rows, ncol = num_cols))
    return(frame)
}

لإنشاء إطار فارغ أثناء تحديد فئة كل عمود ، ما عليك سوى تمرير متجه لأنواع البيانات المطلوبة إلى الوظيفة التالية:

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

استخدم على النحو التالي:

df <- create_empty_table(3, 3, c('character','logical','numeric'))

الذي يعطي:

   X1  X2 X3
1 <NA> NA NA
2 <NA> NA NA
3 <NA> NA NA

لتأكيد اختياراتك ، قم بتشغيل التالي:

lapply(df, class)

#output
$X1
[1] "character"

$X2
[1] "logical"

$X3
[1] "numeric"






dataframe