একটি খালি ডেটা ফ্রেম তৈরি করুন


480

আমি কোনও সারি ছাড়াই একটি ডেটা.ফ্রেম শুরু করার চেষ্টা করছি। মূলত, আমি প্রতিটি কলামের জন্য ডেটা ধরণের নির্দিষ্ট করতে এবং তাদের নাম উল্লেখ করতে চাই, তবে ফলস্বরূপ কোনও সারি তৈরি হয়নি।

আমি এখন অবধি সবচেয়ে ভাল করতে সক্ষম হলাম এরকম কিছু:

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

যা আমি চেয়েছিলাম এমন সমস্ত ডেটা ধরণের এবং কলামের নাম যুক্ত একক সারি সহ একটি ডেটা.ফ্রেম তৈরি করে, তবে একটি অকেজো সারিও তৈরি করে যা পরে অপসারণ করা দরকার।

এই কাজ করতে একটি ভাল উপায় আছে কি?

উত্তর:


651

খালি ভেক্টর দিয়ে কেবল এটি সূচনা করুন:

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শূন্য সারি সহ একটির সাথেও কাজ করবে ।


3
যদি আমি NULL দিয়ে সমস্ত ক্ষেত্র শুরু করি তবে এটি কি একই হবে?
yosukesabai

8
@ ইউসুকেসাবাই: না, আপনি যদি কলামটি এনআউএলএল দিয়ে শুরু করেন তবে কলামটি যুক্ত হবে না :)
ডিগএমআল

6
@ ইউসুকেসাবাই: data.frameকলামগুলি টাইপ করেছেন, তাই হ্যাঁ, আপনি যদি কোনও একটি শুরু করতে চান তবে data.frameঅবশ্যই কলামগুলির
ধরণটি

1
@ জ্যাক্স্রামোস: ভাল, আসলে data.frameকলামগুলির প্রকারের " আদিমতা " সত্যিই সীমাবদ্ধ নয় (উদাহরণস্বরূপ, আপনি তারিখগুলির একটি কলাম বা উপাদানগুলির তালিকা সমেত একটি কলামও যুক্ত করতে পারেন)। এছাড়াও, এই প্রশ্নটি একটি নিখুঁত রেফারেন্স নয়, উদাহরণস্বরূপ আপনি যদি কলামের সঠিক প্রকারটি নির্দিষ্ট না করেন তবে আপনি বিভিন্ন ধরণের কলাম যুক্ত করে আরও সারি যুক্ত অবরুদ্ধ করবেন না ... সুতরাং, আমি একটি নোট যুক্ত করব, তবে না সমস্ত আদিম প্রকারের সাথে একটি উদাহরণ কারণ এটি সমস্ত সম্ভাবনাকে কাভার করে না ...
digEmAll

3
@ ইউজার 4050: প্রশ্নটি একটি খালি ডেটা ফ্রেম তৈরির বিষয়ে ছিল, সুতরাং যখন সারিগুলির সংখ্যা শূন্য হয় ... সম্ভবত আপনি এনএতে পূর্ণ একটি ডেটা ফ্রেম তৈরি করতে চান ... সেই ক্ষেত্রে আপনি যেমন ব্যবহার করতে পারেনdata.frame(Doubles=rep(as.double(NA),numberOfRow), Ints=rep(as.integer(NA),numberOfRow))
ডিগএমএল

139

আপনার যদি ইতিমধ্যে একটি বিদ্যমান ডেটা ফ্রেম থাকে তবে আসুন এটিতেdf যে কলামগুলি আপনি চান সেগুলি আছে তবে আপনি সমস্ত সারি সরিয়ে খালি ডেটা ফ্রেম তৈরি করতে পারেন:

empty_df = df[FALSE,]

লক্ষ্য করুন যে dfএখনও ডেটা রয়েছে, কিন্তু empty_dfনা।

আমি এই প্রশ্নটি খালি সারিগুলির সাথে কীভাবে একটি নতুন উদাহরণ তৈরি করতে চাইছি তা খুঁজে পেয়েছি, তাই আমি মনে করি এটি কিছু লোকের পক্ষে সহায়ক হতে পারে।


2
বিস্ময়কর ধারণা। সারিগুলির কোনওটিই রাখুন না, সমস্ত কলামই রাখুন। যিনি ডাউনভোট করেছেন তিনি কিছু মিস করেছেন।
রাম নরসিমহান

1
ভাল সমাধান, তবে আমি দেখতে পেয়েছি যে আমি 0 টি সারি সহ একটি ডেটা ফ্রেম পেয়েছি। ডাটা ফ্রেমের আকার একই রাখার জন্য, আমি নতুন_ডিএফ = ডিএফ [এনএ,] পরামর্শ দিই। এটি নতুন ডেটা ফ্রেমে আগের কোনও কলাম সংরক্ষণ করতে দেয়। উদাহরণস্বরূপ আসল ডিএফ থেকে "তারিখ" কলামটি পাওয়ার জন্য (বিশ্রাম এনএ রাখার সময়): নতুন_ডিএফ $ তারিখ <- ডিএফ $ তারিখ।
কাটিয়া

2
@ কাট্যা, আপনি যদি df[NA,]এটি করেন তবে সূচকেও প্রভাব ফেলবে (যা আপনি চান তা সম্ভবত সম্ভাবনা নেই), আমি পরিবর্তে ব্যবহার করব df[TRUE,] = NA; তবে লক্ষ্য করুন যে এটি আসলটি ওভাররাইট করবে। আপনাকে প্রথমে ডেটাফ্রেমটি অনুলিপি করতে হবে copy_df = data.frame(df)এবং তারপরেcopy_df[TRUE,] = NA
toto_tico

3
@ কাট্যা, বা আপনি সহজেই এর empty_dfসাথে খালি সারি যুক্ত করতে পারেন empty_df[0:nrow(df),] <- NA
টোটো_টিকো

1
@Katya, আপনি একটি backquote ( `) আপনি কোড হিসেবে চিহ্নিত করতে চাই কি কাছাকাছি ব্যবহার করুন, এবং সেখানে অন্যান্য উপাদান তির্যক * ব্যবহার করে, এবং সাহসী ব্যবহার **। আপনি সম্ভবত এসও এর সমস্ত মার্কডাউন সিনট্যাক্সটি পড়তে চান । এটি বেশিরভাগই কেবল উত্তরগুলির জন্য অর্থবোধ করে।
টোটো_টিকো

79

কলামের ধরণ উল্লেখ না করে আপনি এটি করতে পারেন

df = data.frame(matrix(vector(), 0, 3,
                dimnames=list(c(), c("Date", "File", "User"))),
                stringsAsFactors=F)

4
সেক্ষেত্রে কলামটি ভেক্টর প্রতি লজিকাল হিসাবে ডিফল্ট টাইপ হয় (), তবে তারপরে ডিএফ-এ যুক্ত হওয়া উপাদানগুলির ধরণের সাথে ওভাররাইড করা হয়। Str (df), df [1,1] <- 'x'
ডেভ এক্স

58

আপনি 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)

উন্নতির জন্য রিচার্ড স্ক্রিভেনকে ধন্যবাদ


4
অথবা তবুও read.table(text = "", ...)আপনার স্পষ্টভাবে কোনও সংযোগ খোলার দরকার নেই।
রিচ স্ক্রিভেন 18

Snazzy। সম্ভবত সবচেয়ে প্রসার্য / জন্য এই কাজ করার automable পথ অনেক সম্ভাব্য কলাম
MichaelChirico

3
read.csvপদ্ধতির এছাড়াও সাথে কাজ করে readr::read_csv, যেমন read_csv("Date,File,User\n", col_types = "Dcc")। এইভাবে আপনি সরাসরি প্রয়োজনীয় কাঠামোর একটি খালি টিবল তৈরি করতে পারেন।
হিথার টার্নার

27

এটি করার সর্বাধিক দক্ষ উপায় হল structureশ্রেণি রয়েছে এমন একটি তালিকা তৈরি করতে ব্যবহার করা "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)

এটি বর্তমানে গৃহীত উত্তরের তুলনায় দৃষ্টিকোণে রাখার জন্য, এখানে একটি সাধারণ মানদণ্ড দেওয়া হল:

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

data.tableএটিতে একটি .internal.selfrefবৈশিষ্ট্য থাকে যা data.tableফাংশনগুলি কল না করে নকল করা যায় না । আপনি কি নিশ্চিত যে আপনি এখানে কোনও দলিলবিহীন আচরণের উপর নির্ভর করছেন না?
অ্যাডাম রাইজকোভস্কি

@ অ্যাডাম রাইজকোভস্কি আমার মনে হয় আপনি বেস "ডেটাফ্রেম" শ্রেণি এবং ডেটা টেবিল প্যাকেজ থেকে অ্যাড-অন "ডেটা.ট্যাবিল" শ্রেণিটি বিভ্রান্ত করছেন ।
থমাস

হ্যাঁ. স্পষ্টভাবে. আমার খারাপ। আমার শেষ মন্তব্য উপেক্ষা করুন। অনুসন্ধান করার সময় আমি এই থ্রেডটি পেরিয়ে এসেছিলাম data.tableএবং ধরে নিয়েছিলাম যে গুগল আমার যা চাইছে তা খুঁজে data.tableপেয়েছে এবং এখানকার সবকিছুই সম্পর্কিত-সম্পর্কিত।
অ্যাডাম রাইজকোভস্কি

1
@ পেট্রিকটি এখানে যাচাই করে না যে আপনার কোডটি যা করছে তা কোনও অর্থবোধ করে। data.frame()নামকরণ, রোমন নাম ইত্যাদির উপর চেক সরবরাহ করে
থমাস

26

শুধু ঘোষণা

table = data.frame()

আপনি যখন rbindপ্রথম লাইনে চেষ্টা করবেন এটি কলাম তৈরি করবে


2
"আমি প্রতিটি কলামের জন্য ডেটা ধরণের উল্লেখ করতে এবং তাদের নাম রাখতে চাই" এর ওপির প্রয়োজনীয়তাগুলি সত্যিই পূরণ করে না। তাহলে পরবর্তী ধাপে একটি হল rbindএই, ভাল কাজ করবে না ...
গ্রেগর টমাস

যাইহোক, এই সহজ সমাধানের জন্য ধন্যবাদ। আমি নির্দিষ্ট কলামগুলির সাথে একটি ডেটা ফ্রেমও শুরু করতে চেয়েছিলাম যেহেতু আমি ভেবেছিলাম যে rbind কেবল তখনই ব্যবহার করা যেতে পারে যদি কলামগুলি দুটি ডেটাফ্রেমের সাথে মিলে যায়। এটি মনে হয় না। আমি অবাক হয়ে গিয়েছিলাম যে আরবিন্ড ব্যবহার করার সময় আমি খুব সহজেই একটি ডেটা.ফ্রেম শুরু করতে পারি। ধন্যবাদ।
জিওর্ডানো

4
এখানে সেরা প্রস্তাবিত সমাধান। আমার জন্য, প্রস্তাবিত উপায়টি ব্যবহার করে, পুরোপুরি সাথে কাজ করে rbind()
কটস

17

আপনি যদি স্বল্পতা খুঁজছেন:

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

সুতরাং কলামের নামগুলি আলাদাভাবে নির্দিষ্ট করার দরকার নেই। আপনি ডেটা ফ্রেম পূরণ না করা পর্যন্ত আপনি ডিফল্ট কলামের ধরণের লজিকাল পাবেন।


read.csv পাঠ্যের যুক্তিটিকে পার্স করে যাতে আপনি কলামের নাম পান get এটা তোলে read.table চেয়ে বেশি কম্প্যাক্ট হয় (পাঠ্য = "", col.names = C ( "col1", "col2"))
মার্ক

আমি পেয়েছি:Error in data.frame(..., check.names = FALSE) : arguments imply differing number of rows: 0, 2
চূড়ান্ত_লিকা_স্প্যাডার

এটি ওপির প্রয়োজনীয়তা পূরণ করে না, "আমি প্রতিটি কলামের জন্য ডেটা ধরণের উল্লেখ করতে চাই" , যদিও এটি করার জন্য সম্ভবত এটি সংশোধন করা যেতে পারে।
গ্রেগর থমাস

14

আমি নিম্নলিখিত কোড ব্যবহার করে খালি ডেটা ফ্রেম তৈরি করেছি

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

এবং নীচে একইভাবে পপুল করার জন্য কয়েকটি সারি বেঁধে দেওয়ার চেষ্টা করেছিলেন।

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

তবে এটি নিম্নলিখিত হিসাবে ভুল কলামের নাম দেওয়া শুরু করে

  X3 X4
1  3  4

এর সমাধান হ'ল নিউরোকে নিম্নরূপে df টাইপ করুন convert

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

নীচে কলামের নামগুলি প্রদর্শিত হলে এখন সঠিক ডেটা ফ্রেম দেয়

  id nobs
1  3   4 

7

একটি খালি ডেটা ফ্রেম তৈরি করতে , নিম্নলিখিত ফাংশনটিতে প্রয়োজনীয় সারি এবং কলামগুলির সংখ্যাটি পাস করুন:

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(frame[,i])}
    if(type_vec[i] == 'character') {frame[,i] <- as.character(frame[,i])}
    if(type_vec[i] == 'logical') {frame[,i] <- as.logical(frame[,i])}
    if(type_vec[i] == 'factor') {frame[,i] <- as.factor(frame[,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"

1
এটি ওপি-র প্রয়োজনীয়তা পূরণ করে না, "আমি প্রতিটি কলামের জন্য ডেটা ধরণের উল্লেখ করতে চাই"
গ্রেগর টমাস

6

আপনি যদি একটি খালি ডেটা তৈরি করতে চান ডায়নামিক নামগুলি (একটি ভেরিয়েবলের নামগুলি) দিয়ে ফ্রেম করুন, এটি সহায়তা করতে পারে:

names <- c("v","u","w")
df <- data.frame()
for (k in names) df[[k]]<-as.numeric()

আপনার যদি প্রয়োজন হয় তবে আপনি প্রকারগুলিও পরিবর্তন করতে পারেন। মত:

names <- c("u", "v")
df <- data.frame()
df[[names[1]]] <- as.numeric()
df[[names[2]]] <- as.character()

4

আপনার যদি ডেটার প্রকারগুলি স্পষ্টভাবে উল্লেখ না করাতে আপত্তি না থাকে তবে আপনি এটি এইভাবে করতে পারেন:

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)

4

ব্যবহার করে data.tableআমরা প্রতিটি কলামের জন্য ডেটা প্রকারগুলি নির্দিষ্ট করতে পারি।

library(data.table)    
data=data.table(a=numeric(), b=numeric(), c=numeric())

3

আপনি যদি 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

1

বলুন আপনার কলামের নামগুলি গতিশীল, আপনি একটি খালি সারি-নামক ম্যাট্রিক্স তৈরি করতে এবং এটি একটি ডেটা ফ্রেমে রূপান্তর করতে পারেন।

nms <- sample(LETTERS,sample(1:10))
as.data.frame(t(matrix(nrow=length(nms),ncol=0,dimnames=list(nms))))

এটি ওপি-র প্রয়োজনীয়তা পূরণ করে না, "আমি প্রতিটি কলামের জন্য ডেটা ধরণের উল্লেখ করতে চাই"
গ্রেগর টমাস

1

এই প্রশ্নটি আমার উদ্বেগগুলিকে সুনির্দিষ্টভাবে সমাধান করে নি ( এখানে বর্ণিত ) তবে যদি কেউ প্যারামিটারাইজড সংখ্যক কলাম এবং কোনও জোর না করে এটি করতে চায়:

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

বিভাজন লিঙ্কিত প্রশ্নে যেমন বলা হয়েছে,

... কারণ [জবরদস্তি] ঘটে [যখন সিবাইন্ডিং ম্যাট্রিক্স এবং তাদের উপাদানগুলির প্রকারগুলি] ম্যাট্রিক্সে কেবলমাত্র একক ডেটা টাইপ থাকতে পারে। আপনি যখন 2 ম্যাট্রিককে সিবাইন্ড করেন, ফলাফলটি এখনও ম্যাট্রিক্স হয় এবং তাই ভেরিয়েবলগুলি ডেটা-ফ্রেমে রূপান্তরিত করার আগে একক প্রকারে জোর করা হয় ra


1

আপনার যদি ইতিমধ্যে ডেটাফ্রেম থাকে তবে আপনি ডেটাফ্রেম থেকে মেটাডেটা (কলামের নাম এবং প্রকারগুলি) বের করতে পারবেন (যেমন আপনি যদি কোনও বিইউজি নিয়ন্ত্রণ করছেন যা কেবলমাত্র নির্দিষ্ট ইনপুট দিয়ে চালিত হয় এবং খালি ডামি ডেটাফ্রেমের প্রয়োজন হয়):

colums_and_types <- sapply(df, class)

# prints: "c('col1', 'col2')"
print(dput(as.character(names(colums_and_types))))

# prints: "c('integer', 'factor')"
dput(as.character(as.vector(colums_and_types)))

এবং তারপরে read.tableখালি ডেটা ফ্রেম তৈরি করতে ব্যবহার করুন

read.table(text = "",
   colClasses = c('integer', 'factor'),
   col.names = c('col1', 'col2'))
আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.