【发布时间】:2020-08-10 04:30:31
【问题描述】:
我正在尝试从矩阵中随机抽样(b 下面),但我希望得到的样本矩阵在每列中的零比例等于另一个矩阵的比例( a 下面)。我正在尝试使用 sample() 函数来执行此操作,但我并没有很高兴。下面是一些可重现的代码,希望能解释我的问题:
编辑:顺便提一下,我不希望增加或编辑任何行,而是从b 进行随机抽样,以便生成矩阵; b_sample 与 a 的零分布大致相等
set.seed(1234)
# matrix a is the matrix that holds the distribution of zeros I want to match
a <- matrix(as.integer(rexp(200, rate=.1)), ncol=20)
# matrix b is the matrix to be sampled from
b <- matrix(as.integer(rexp(2000, rate=.1)), ncol=20)
a 看起来像:
[,1] [,2] [,3] [,4] [,5]
[1,] 6 0 6 1 22
[2,] 19 6 0 23 19
[3,] 8 22 8 5 0
[4,] 24 17 28 3 0
b 看起来像:
[,1] [,2] [,3] [,4] [,5]
[1,] 1 1 10 5 9
[2,] 26 1 3 2 2
[3,] 4 8 3 0 0
[4,] 2 10 35 3 11
[5,] 1 3 16 0 6
[6,] 2 4 2 16 2
[7,] 3 18 13 6 17
[8,] 0 2 9 0 13
[9,] 2 15 6 27 30
[10,] 1 2 7 9 15
[11,] 13 0 5 1 2
[12,] 18 12 9 27 33
[13,] 0 20 3 18 1
[14,] 5 7 7 16 4
[15,] 5 6 4 5 2
[16,] 0 7 5 10 7
[17,] 3 20 5 14 34
[18,] 28 0 10 5 8
[19,] 33 0 2 6 13
[20,] 7 28 0 11 8
我提取a 的每一列中的零分布以用于采样
dist<-apply(a,2, function(x) sum(x!=0)/length(x))
dist
[1] 1.00 0.75 0.75 1.00 0.50
然后我继续尝试从 b 中采样以保持与 a 相同的行数
b_sample<-b[sample(x=nrow(b),
size=4,
replace=F
)
,]
这可行,但我希望b_sample 在每列中的零比例与a 相同。我已经尝试过这样做
b_sample<-b[sample(x=nrow(b),
size=4,
replace=F,
prob=dist
)
,]
但我得到一个错误:
Error in sample.int(x, size, replace, prob) :
incorrect number of probabilities
我不确定我这样做的格式是否错误,或者sample() 函数根本不是要使用的更正函数。任何帮助将不胜感激!
编辑 2:更新如下
我找到了一种从b 中采样的方法,并使生成的b_sample 中的零比例与原始b 相同。这不是我想要得到的,我希望比例等于a 中的比例,但它可能会更好地了解我想要做什么。有关上述示例的开发,请参见下文
首先我将b 放入一个数据框并索引行以使用dplyr 和groupby()
b_df<-as.data.frame(b)
b_df <- b_df %>%
mutate(n = row_number()) %>% #create row number
select(n, everything()) # put row number at the front of the dataset
b_df
n V1 V2 V3 V4 V5
1 1 19 1 29 2 9
2 2 7 20 1 3 9
3 3 3 25 8 9 22
4 4 9 0 20 9 0
5 5 2 12 14 4 2
6 6 10 22 9 1 9
7 7 0 9 16 1 4
8 8 3 3 14 23 2
9 9 7 0 7 1 0
10 10 9 0 26 2 6
11 11 4 19 0 2 6
12 12 0 2 1 7 4
13 13 16 16 25 2 3
14 14 0 1 1 7 9
15 15 8 14 0 9 5
16 16 0 14 9 5 0
17 17 43 27 14 1 4
18 18 9 0 13 4 9
19 19 0 8 3 9 13
20 20 34 36 1 7 20
然后我创建一个二进制数据框来指示每个单元格是否具有 0 或值
b_df_0[,-1]<-as.data.frame(lapply(b_df[,-1],function(x) x==0))
b_df_0
n V1 V2 V3 V4 V5
1 1 FALSE FALSE FALSE FALSE FALSE
2 2 FALSE FALSE FALSE FALSE FALSE
3 3 FALSE FALSE FALSE FALSE FALSE
4 4 FALSE TRUE FALSE FALSE TRUE
5 5 FALSE FALSE FALSE FALSE FALSE
6 6 FALSE FALSE FALSE FALSE FALSE
7 7 TRUE FALSE FALSE FALSE FALSE
8 8 FALSE FALSE FALSE FALSE FALSE
9 9 FALSE TRUE FALSE FALSE TRUE
10 10 FALSE TRUE FALSE FALSE FALSE
11 11 FALSE FALSE TRUE FALSE FALSE
12 12 TRUE FALSE FALSE FALSE FALSE
13 13 FALSE FALSE FALSE FALSE FALSE
14 14 TRUE FALSE FALSE FALSE FALSE
15 15 FALSE FALSE TRUE FALSE FALSE
16 16 TRUE FALSE FALSE FALSE TRUE
17 17 FALSE FALSE FALSE FALSE FALSE
18 18 FALSE TRUE FALSE FALSE FALSE
19 19 TRUE FALSE FALSE FALSE FALSE
20 20 FALSE FALSE FALSE FALSE FALSE
然后,我使用来自dplyr 的group_by 和sample_frac 从b 中采样,以等于a 中的采样数。
proportion <- nrow(a)/nrow(b)
sample <- b_df_0 %>%
group_by(V1,V2,V3,V4,V5) %>% #any number of variables you wish to partition by proportionally
sample_frac(proportion) # proportion of the original df you wish to sample
b_df[b_df$n %in% sample$n,]
#The above approach would work if you can get a proportions = b proportions
n V1 V2 V3 V4 V5
2 2 7 20 1 3 9
19 19 0 8 3 9 13
20 20 34 36 1 7 20
这种方法不是我想要的,但是当我希望它们基于a 时,比例基于b。任何关于如何做到这一点的帮助都会很棒!谢谢!
【问题讨论】:
标签: r dataframe matrix random dplyr