我有一个包含20个要素的数据集。我希望创建一个数据集列表,其中包含来自原始数据集的特征的随机子集。
例如-[dataset[, c(1,3,4)], dataset[, c(2,3,5,11,20)]]
。
我正在尝试以下代码
selectors = array(runif(2000), dim=c(100, 20, 1))
list_datasets = vector("list", 100)
i = 1
while(i < 100)
list_datasets[[i]] = dataset[, selectors[i,,1] > 0.5]
i = i + 1
在这里,我的dataset
具有20个特征,在这20个特征中,我需要100个具有随机特征的数据集。因此,我创建了selectors
数组,方法是首先创建一个带有随机值的大小为2000的向量,然后将其设置为100 * 20。然后,在while
循环中,仅当为其生成的随机值大于0.5时,我才尝试向list_datasets[[i]]
添加一个功能。希望我能够自我解释
但这很慢。我是R的新手,想知道实现我正在尝试的最佳方法是什么。
答案 0 :(得分:0)
我不确定我是否了解您的设置,如果错过了一些内容,请纠正我。我的理解是,您有一个数据集(我创建了一个大小为100行x 20个特征的假数据集),并希望使用特征的随机子集创建100个新数据集。您可以通过生成随机的统一值并检查每个值是否大于0.5来生成要素的随机子集。
我在这里有两个选择,一个使用lapply
,另一个使用for
循环。
apply函数通常比循环要快(我认为您想使用for
循环,而不是这里的while
循环)。
其他更改:
1)按照@Krash的建议使用布尔掩码,因为您可以检查循环外的每个值是否大于0.5,因为它是否不取决于i
。
2)selectors
可以是2d
set.seed(123)
# Original dataset: assume it's 100 x 20 features
dataset <- array(rnorm(2000), dim = c(100, 20))
## Original (Option 0: while loop)
system.time({
# Select features: 100 x 20 x 1 (one row per dataset)
selectors = array(runif(2000), dim = c(100, 20, 1));
# Initialize list
list_datasets = vector("list", 100);
# Fill in list
i = 1;
while(i < 100) {
list_datasets[[i]] = dataset[, selectors[i,,1] > 0.5];
i = i + 1 # This causes an off-by-one error, as list_datasets[[100]] is never filled in
}
})
## user system elapsed
## 0.006 0.000 0.006
# Option 1: for loop
system.time({
# Select: boolean mask: 100 x 20 (need one row to create each dataset)
selectors = array(runif(2000), dim = c(100, 20));
selectors = selectors < 0.5
# Initialize list
list_datasets = vector("list", 100);
# Fill in list
for (i in 1:100) {
list_datasets[[i]] = dataset[ , selectors[i, ]]
}
})
## user system elapsed
## 0.004 0.000 0.005
# Option 2: lapply
system.time({
# Select: boolean mask: 100 x 20 (need one row to create each dataset)
selectors = array(runif(2000), dim = c(100, 20));
selectors = selectors < 0.5
# Fill in list
list_datasets <- lapply(1:100, FUN = function(x) dataset[ , selectors[x, ]])
})
## user system elapsed
## 0.003 0.000 0.003
显然,每次运行语句所需的时间会有所不同,但希望其中一些建议的更改可以提高速度。
作为检查以确保代码符合我的期望:
# Check number of cols per dataset
list_datasets %>%
purrr::map_int(~ncol(.))
## [1] 8 7 9 12 11 13 11 10 10 14 14 7 8 10 10 9 14 10 6 11 13 8 7 8 10 12 9 11 9 9 13
## [32] 12 8 14 11 11 8 10 11 8 10 13 12 10 6 10 10 12 9 9 10 11 7 8 11 9 11 9 7 9 9 11
## [63] 14 9 9 9 9 13 13 14 12 9 10 9 12 8 11 14 9 7 12 7 6 11 11 7 9 8 12 10 12 9 11
## [94] 13 12 16 9 8 11 10
其他想法:您可以在循环中添加这样的行(或selectors
lapply
,而不是通过随机制服创建FUN
数组,而每一行都对应一个新数据集。 )。
include_feature <- sample(0:1, size = 20, replace = TRUE)
include_feature
## [1] 0 0 1 0 0 0 1 1 1 0 1 1 1 0 1 0 0 0 0 1