2012-11-23 7 views
15

मैं एक डेटा सेट को विभाजित करने की कोशिश कर रहा हूं जिसमें मेरे पास आर, 2/3 प्रशिक्षण के लिए और 1/3 परीक्षण के लिए है। मेरे पास एक वर्गीकरण चर है, और सात संख्यात्मक चर है। प्रत्येक अवलोकन को ए, बी, सी, या डीअवलोकनों के कई वर्गों के आधार पर आर में विभाजन डेटा सेट

सादगी के लिए, मान लें कि वर्गीकरण चर, सीएल, पहले 100 अवलोकनों के लिए ए है, बी के लिए 101 से 200, सी 300 तक , और डी 400 तक। मैं एक विभाजन प्राप्त करने की कोशिश कर रहा हूं जिसमें ए, बी, सी, और डी के प्रत्येक अवलोकन के 2/3 हैं (जैसा कि पूरे डेटा सेट के लिए अवलोकनों के 2/3 प्राप्त करने के विपरीत है चूंकि इसमें प्रत्येक वर्गीकरण की समान मात्रा नहीं होगी)।

जब मैं डेटा के सबसेट से नमूना करने का प्रयास करता हूं, जैसे कि sample(subset(data, cl=='A')), पंक्तियों के बजाय स्तंभों को फिर से व्यवस्थित किया जाता है।

संक्षेप में, मेरा लक्ष्य ए, बी, सी, और डी से प्रत्येक प्रशिक्षण डेटा के रूप में 67 यादृच्छिक अवलोकन होना है, और प्रत्येक ए, बी, सी, और डी के परीक्षण के रूप में शेष 33 अवलोकनों को संग्रहित करना है डेटा। मुझे मेरा बहुत ही समान प्रश्न मिला है, लेकिन यह कई चरों में कारक नहीं था।

उत्तर

5

इस लंबे समय तक हो सकता है लेकिन मुझे लगता है कि इसे और अधिक सहज है और आधार आर में किया जा सकता है;)

# create the data frame you've described 
x <- 
    data.frame(
     cl = 
      c( 
       rep('A' , 100) , 
       rep('B' , 100) , 
       rep('C' , 100) , 
       rep('D' , 100) 
      ) , 

     othernum1 = rnorm(400) , 
     othernum2 = rnorm(400) , 
     othernum3 = rnorm(400) , 
     othernum4 = rnorm(400) , 
     othernum5 = rnorm(400) , 
     othernum6 = rnorm(400) , 
     othernum7 = rnorm(400) 
    ) 

# sample 67 training rows within classification groups 
training.rows <- 
    tapply( 
     # numeric vector containing the numbers 
     # 1 to nrow(x) 
     1:nrow(x) , 

     # break the sample function out by 
     # the classification variable 
     x$cl , 

     # use the sample function within 
     # each classification variable group 
     sample , 

     # send the size = 67 parameter 
     # through to the sample() function 
     size = 67 
    ) 

# convert your list back to a numeric vector 
tr <- unlist(training.rows) 

# split your original data frame into two: 

# all the records sampled as training rows 
training.df <- x[ tr , ] 

# all other records (NOT sampled as training rows) 
testing.df <- x[ -tr , ] 
+0

शानदार! मैंने अभी तक असूचीबद्ध फ़ंक्शन के बारे में नहीं सुना है। ऐसा लगता है कि मैं वही कर रहा हूं जो मैं चाहता हूं, और जो कुछ मैंने किया है उससे कम तरीके से। – Danny

4

निम्नलिखित अपने data.frame के मूल्यों "train" या "test" के साथ एक set स्तंभ जोड़ देगा:

library(plyr) 
df <- ddply(df, "cl", transform, set = sample(c("train", "test"), length(cl), 
               replace = TRUE, prob = c(2, 1))) 

आप आधार ave समारोह का उपयोग कर कुछ इसी तरह प्राप्त कर सकते हैं, लेकिन मैं के लिए ddply सुंदर स्वच्छ (पठनीय) लगता है यह विशेष उपयोग।

train.data <- subset(df, set == "train") 
test.data <- subset(df, set == "test") 

फ़ॉलो-अप:

तब आप अपने डेटा subset समारोह का उपयोग कर विभाजित कर सकते हैं वास्तव में 2/3 और 1/3 आकार में प्रत्येक समूह विभाजित करने के लिए, आप का उपयोग कर सकते हैं:

df <- ddply(df, "cl", transform, 
      set = sample(c(rep("train", round(2/3 * length(cl)), 
          rep("test", round(1/3 * length(cl))))) 
+0

क्या आपका मतलब बदलना है, संक्षेप में नहीं? – frankc

+0

@ फ्रैंक। हाँ धन्यवाद। फिक्स्ड। – flodel

+0

मैं इसके बारे में गलत हो सकता हूं, लेकिन ऐसा लगता है कि यह हर बार प्रत्येक समूह से मुझे बिल्कुल 2/3 नहीं दे सकता है। क्या यह सिर्फ यह नहीं कह रहा है कि संभावना 2/3 है? मेरी समस्या यह है कि मुझे हर बार प्रत्येक समूह से 67 की आवश्यकता होती है। – Danny

16

वास्तव में मशीन लर्निंग समस्याओं से निपटने के लिए एक अच्छा पैकेज कैरट है और यह एक समारोह createDataPartition() कि काफी एक आपूर्ति कारक के प्रत्येक स्तर से 2/3rds इस नमूने करता है शामिल हैं:

#2/3rds for training 
library(caret) 
inTrain = createDataPartition(df$yourFactor, p = 2/3, list = FALSE) 
dfTrain=df[inTrain,] 
dfTest=df[-inTrain,] 
+0

यह एक आकर्षण की तरह काम करता है – salvu

1

स्तरीकरण के लिए कई कारकों के साथ क्रॉस-सत्यापन के लिए विभाजन डेटा के लिए अपना स्वयं का फ़ंक्शन बनाने के दौरान इस समस्या में उछाल आया। आप डेटा को 3 (या एन) समान रूप से आकार वाले हिस्सों में विभाजित करके डेटा को समान रूप से विभाजित करते समय डेटा को समान रूप से विभाजित करते समय डेटा सेट कर सकते हैं और फिर परीक्षण सेट के रूप में एक तिहाई का चयन कर सकते हैं और फिर प्रशिक्षण सेट के रूप में आराम कर सकते हैं। मैं आर

यहाँ में इस तरह के सूची के रूप में तत्वों संभाल होता है, एक समारोह है कि मैं आधार पैकेज कि कई स्तरीकरण कारकों का समर्थन करता है का उपयोग करके बनाया है स्तंभ संख्या या क्षेत्रों के स्तंभ नाम आप स्तर के रूप में करना चाहते हैं कि के रूप में इंगित (mtcars डेटासेट उदाहरण)।मुझे लगता है कि नहीं बल्कि ddply कार्यक्षमता में समान है, अपवाद है कि आप भी स्तंभ संख्या का उपयोग कर सकते हैं और साथ जिसके परिणामस्वरूप सबसेट एक सूची अंदर दिया जाता है कि:

# Function that partitions data into a number of equally (or almost-equally) sized bins that do not overlap, and returns the data bins as a list 
# Useful for cross validation 
partition_data <- function(
    # Data frame to partition (default example: mtcars data, assuming rows correspond to observations) 
    dat = mtcars, 
    # Number of equally sized bins to partition to (default here: 2 bins) 
    bins = 2, 
    # Stratification element, homogeneous subpopulations according to a column that should be subsampled, 
    # Observations within a substrata are divided equally to the partitioned bins 
    stratum = NA 
){ 
    # Total number of observations 
    nobs <- dim(dat)[1] 
    # Allocation vector, to be used for randomly distributing the samples to the bins 
    loc <- rep(1:bins, times=ceiling(nobs/bins))[1:nobs] 


    # If the dataset is stratified, each subpopulation is distributed equally to the bins, otherwise the whole population is the "subpopulation" 
    if(missing(stratum)){ 
     pops <- list(sample(1:dim(dat)[1])) 
    }else{ 
     uniqs <- na.omit(as.matrix(unique(dat[,stratum]))) 
     pops <- list() 
     for(i in 1:nrow(uniqs)){ 
      # If some of the stratified fields include NA-values, these will not be included in the sampling 
      w <- apply(as.matrix(dat[,stratum]), MARGIN=1, FUN=function(x) all(x==uniqs[i,])) 
      pops[[i]] <- sample(which(w)) 
     } 
    } 
    indices <- vector(length=nobs) 
    # Assign the group indices according to permutated samples within each subpopulation 
    indices[unlist(pops)] <- loc 
    # Assign observations to separate locations in a list 
    partitioned_data <- lapply(unique(indices), FUN=function(x) dat[x==indices,]) 
    # Return the result 
    partitioned_data 
} 

यह कैसे काम करता का उदाहरण; इस काल्पनिक उदाहरण में एक कारक है 'बनाम' के लिए इच्छा होती है और 'हूँ' समान रूप से सभी डिब्बे में प्रतिनिधित्व करने की:

set.seed(1) 

# Stratified sampling, so that combinations of binary covariates vs = {0,1} & am = {0,1} appear equally over the randomized bins of data 
pt <- partition_data(mtcars, stratum=c("vs", "am"), bins=3) 

# Instances are distributed equally 
lapply(pt, FUN=function(x) table(x[,c("vs","am")])) 
#> lapply(pt, FUN=function(x) table(x[,c("vs","am")])) 
#[[1]] 
# am 
#vs 0 1 
# 0 4 2 
# 1 3 2 
# 
#[[2]] 
# am 
#vs 0 1 
# 0 4 2 
# 1 2 3 
# 
#[[3]] 
# am 
#vs 0 1 
# 0 4 2 
# 1 2 2 

# 10 or 11 samples (=rows) per partition of data (data had 11 columns) 
lapply(pt, FUN=dim) 

# Training set containing 2/3 of the stratified samples 
# Constructed by dropping out the first third of samples 

train <- do.call("rbind", pt[-1]) 

# Test set containing the remaining 1/3 

test <- pt[[1]] 

# 21 samples in training dataset 
print(dim(train)) 
# 11 samples in testing dataset 
print(dim(test)) 



> print(train) 
        mpg cyl disp hp drat wt qsec vs am gear carb 
Mazda RX4 Wag  21.0 6 160.0 110 3.90 2.875 17.02 0 1 4 4 
Datsun 710   22.8 4 108.0 93 3.85 2.320 18.61 1 1 4 1 
Hornet 4 Drive  21.4 6 258.0 110 3.08 3.215 19.44 1 0 3 1 
Merc 450SE   16.4 8 275.8 180 3.07 4.070 17.40 0 0 3 3 
Cadillac Fleetwood 10.4 8 472.0 205 2.93 5.250 17.98 0 0 3 4 
Fiat 128   32.4 4 78.7 66 4.08 2.200 19.47 1 1 4 1 
Toyota Corona  21.5 4 120.1 97 3.70 2.465 20.01 1 0 3 1 
Dodge Challenger 15.5 8 318.0 150 2.76 3.520 16.87 0 0 3 2 
Camaro Z28   13.3 8 350.0 245 3.73 3.840 15.41 0 0 3 4 
Ford Pantera L  15.8 8 351.0 264 4.22 3.170 14.50 0 1 5 4 
Volvo 142E   21.4 4 121.0 109 4.11 2.780 18.60 1 1 4 2 
Hornet Sportabout 18.7 8 360.0 175 3.15 3.440 17.02 0 0 3 2 
Duster 360   14.3 8 360.0 245 3.21 3.570 15.84 0 0 3 4 
Merc 230   22.8 4 140.8 95 3.92 3.150 22.90 1 0 4 2 
Merc 280   19.2 6 167.6 123 3.92 3.440 18.30 1 0 4 4 
Merc 450SLC  15.2 8 275.8 180 3.07 3.780 18.00 0 0 3 3 
Honda Civic  30.4 4 75.7 52 4.93 1.615 18.52 1 1 4 2 
Pontiac Firebird 19.2 8 400.0 175 3.08 3.845 17.05 0 0 3 2 
Porsche 914-2  26.0 4 120.3 91 4.43 2.140 16.70 0 1 5 2 
Lotus Europa  30.4 4 95.1 113 3.77 1.513 16.90 1 1 5 2 
Ferrari Dino  19.7 6 145.0 175 3.62 2.770 15.50 0 1 5 6 
> print(test) 
        mpg cyl disp hp drat wt qsec vs am gear carb 
Mazda RX4   21.0 6 160.0 110 3.90 2.620 16.46 0 1 4 4 
Valiant    18.1 6 225.0 105 2.76 3.460 20.22 1 0 3 1 
Merc 240D   24.4 4 146.7 62 3.69 3.190 20.00 1 0 4 2 
Merc 280C   17.8 6 167.6 123 3.92 3.440 18.90 1 0 4 4 
Merc 450SL   17.3 8 275.8 180 3.07 3.730 17.60 0 0 3 3 
Lincoln Continental 10.4 8 460.0 215 3.00 5.424 17.82 0 0 3 4 
Chrysler Imperial 14.7 8 440.0 230 3.23 5.345 17.42 0 0 3 4 
Toyota Corolla  33.9 4 71.1 65 4.22 1.835 19.90 1 1 4 1 
AMC Javelin   15.2 8 304.0 150 3.15 3.435 17.30 0 0 3 2 
Fiat X1-9   27.3 4 79.0 66 4.08 1.935 18.90 1 1 4 1 
Maserati Bora  15.0 8 301.0 335 3.54 3.570 14.60 0 1 5 8 


# Example of sampling without stratification; the binary covariates 'vs' and 'am' are probably not distributed equally over the bins 
lapply(pt2 <- partition_data(mtcars, bins=3), FUN=function(x) table(x[,c("vs","am")])) 

# Stratified according to a single covariate (cylinders) 
lapply(pt3 <- partition_data(mtcars, stratum="cyl", bins=3), FUN=function(x) table(x[,c("cyl")])) 

इस विशेष डाटासेट कि चर्चा की गई में, एंथनी के जवाब से data.frame साथ:

xpt <- partition_data(x, stratum="cl", bins=3) 
# Same as: 
#xpt <- partition_data(x, stratum=1, bins=3) 

train_xpt <- do.call("rbind", xpt[-1]) 
test_xpt <- xpt[[1]] 
#> summary(train_xpt[,"cl"]) 
# A B C D 
#67 66 67 67 
#> summary(test_xpt[,"cl"]) 
# A B C D 
#33 34 33 33 
संबंधित मुद्दे