如何使用Caret库对个体进行面板数据的抽样/分区?

8

我希望将面板数据进行分区,并保留数据的面板性质:

      library(caret)
      library(mlbench)

      #example panel data where id is the persons identifier over years
      data <- read.table("http://people.stern.nyu.edu/wgreene/Econometrics/healthcare.csv",
                    header=TRUE, sep=",", na.strings="NA", dec=".", strip.white=TRUE)

      ## Here for instance the dependent variable is working
      inTrain <- createDataPartition(y = data$WORKING, p = .75,list = FALSE)

      # subset into training
      training <- data[ inTrain,]
      # subset into testing
      testing <- data[-inTrain,]
      # Here we see some intersections of identifiers 
      str(training$id[10:20])
      str(testing$id)

当对数据进行分区或抽样时,我希望避免同一个人(id)被分割为两个数据集。有没有一种方法可以从数据中随机抽样/分区并将个人分配到相应的分区而不是观察结果?

我尝试过抽样:

    mysample <- data[sample(unique(data$id), 1000,replace=FALSE),] 

然而,这样做会破坏数据面板的特性...
2个回答

6

我认为在使用sample()进行采样时存在一个小错误:它像行号一样使用id变量。相反,这个函数需要获取所有属于一个ID的行:

nID <- length(unique(data$id))
p = 0.75
set.seed(123)
inTrainID <- sample(unique(data$id), round(nID * p), replace=FALSE)
training <- data[data$id %in% inTrainID, ] 
testing <- data[!data$id %in% inTrainID, ] 

head(training[, 1:5], 10)
#    id FEMALE YEAR AGE   HANDDUM
# 1   1      0 1984  54 0.0000000
# 2   1      0 1985  55 0.0000000
# 3   1      0 1986  56 0.0000000
# 8   3      1 1984  58 0.1687193
# 9   3      1 1986  60 1.0000000
# 10  3      1 1987  61 0.0000000
# 11  3      1 1988  62 1.0000000
# 12  4      1 1985  29 0.0000000
# 13  5      0 1987  27 1.0000000
# 14  5      0 1988  28 0.0000000


dim(data)
# [1] 27326    41
dim(training)
# [1] 20566    41
dim(testing)
# [1] 6760   41
20566/27326
### 75.26% were selected for training

让我们检查一下班级平衡情况,因为createDataPartition会在所有集合中保持WORKING类别的平衡。

table(data$WORKING) / nrow(data)
#         0         1 
# 0.3229525 0.6770475 
#
table(training$WORKING) / nrow(training)
#         0         1 
# 0.3226685 0.6773315 
#
table(testing$WORKING) / nrow(testing)
#         0         1 
# 0.3238166 0.6761834 
### virtually equal

1
非常感谢。我想你的意思是inTrain而不是inTrainID - Googme
谢谢,已经更正了。这并不重要,但我的意思是强调我们是从ID中进行抽样,而不是从行号中进行抽样。 - thie1e

2
我想向任何查看此内容的人指出caret的groupKFold函数,这对于使用此类数据进行交叉验证非常方便。 来自文档: “要基于组拆分数据,可以使用groupKFold:”
set.seed(3527)
subjects <- sample(1:20, size = 80, replace = TRUE)
folds <- groupKFold(subjects, k = 15) 

折叠后的结果可用作trainControl函数的index参数的输入。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接