基于分布的数据框样本
Sample from data frame based on distribution
我正在尝试从数据框中采样,但条件是样本代表某个标准的分布(在我的例子中。
数据框的结构如下:
df <- data.frame(Locaton = c(A, B, B, B, C, C, ...),
Veg_Species = c(X, Y, Z, Z, Z, Z...),
Date_Diff = c(2, 5, 2, 0, 4, 4...))
重要的是要知道,Veg_Species
的数量不同。这意味着 X
出现了 25 次,例如 Y
45 次和 Z
78 次。现在我想根据最小样本 Date_Diff
的分布从不同的 Veg_Species
中抽样。在那种情况下,这意味着根据 X
.
的 Date_diff
分布从每个物种中抽样
我认为我可以用 dplyr
:
sample.species <- df %>% filter(Veg_Species == 'Z') %>% sample_n(25, replace = TRUE)
但这显然只是从名称为 Z
的所有 Veg_Species
中随机抽样。
我怎样才能把分布也考虑进去?
有关更详细的示例,请单击 here。
在我看来,您想对数据集进行采样,但要保持 X 子集中存在的 Date_diff
分布。
首先您需要确定 X 子集中存在什么。我做了一些看起来像你的假数据:
set.seed(123)
df <- data.frame(Location = sample(LETTERS[1:3], 148, replace = TRUE),
Veg_Species = c(rep("X", 25), rep("Y", 45), rep("Z", 78)),
Date_Diff = trunc(runif(148, 0, 10)))
现在,我们需要为 Veg_Species = X
分配 Date_Diff
。我们可以用 dplyr
:
library(dplyr)
x_dist <- df %>%
filter(Veg_Species == "X") %>%
group_by(Date_Diff) %>%
summarize(count = n())
x_dist
A tibble: 8 x 2
Date_Diff count
<dbl> <int>
1 1 2
2 2 6
3 3 5
4 4 3
5 5 3
6 6 2
7 7 2
8 8 2
现在我们过滤原始数据,nest_by(Date_Diff)
并通过x_dist
中的count
对每个data
进行采样。
set.seed(345)
df_sample <- df %>%
semi_join(x_dist) %>% # Remove all rows with Date_Diff not in x_dist
nest_by(Date_Diff) %>%
inner_join(x_dist) %>%
mutate(data = list(data[sample(1:nrow(data), # sampling the data
size = count,
replace = TRUE),])) %>%
summarize(data) %>% # unnesting the data
select(Location, veg_Species,
Date_Diff, -count) # reordering columns and removing count
df_sample
# A tibble: 25 x 3
# Groups: Date_Diff [8]
Location Veg_Species Date_Diff
<chr> <chr> <dbl>
1 C Z 1
2 A Z 1
3 A Y 2
4 C Z 2
5 B X 2
6 B Z 2
7 B X 2
8 B X 2
9 A Y 3
10 A X 3
# ... with 15 more rows
sample()
中的参数 prob=
是每个样本元素的权重向量。我的想法是使用每行的索引和权重向量进行采样。这将保留分布。
sample_by_distribution <- function(df, dist_weights_col, n, replace=FALSE) {
sampled_indexes <- sample(x=1:nrow(df), size=n, replace=replace, prob = df[, dist_weights_col])
df[sampled_indexes,]
}
通过考虑您案例中的分布权重进行抽样:
sample_df <- sample_by_distribution(df, "Date_Diff", 25, replace=FALSE)
这将对 df
的 25 行进行采样,而每行的概率都在“Date_Diff”列之后。因此,“Veg_Species”的分布也应该保留。
也许您可以尝试对 Date_Diff
的分布进行核密度估计。
1.数据和包
df <- read.csv("http://www.sharecsv.com/dl/2a26bf2c69bfd76e8ddcecd1c3739a31/ex.csv", row.names = 1)
library(dplyr)
2。找到最小的物种
df %>% count(Species)
# Species n
# 1 Adenostoma fasciculatum 95
# 2 Artemisia filifolia 26
# 3 Eriogonum fasciculatum 41
# 4 Tamarix L. 27
3。分布和线性插值的核密度估计
(参考:https://stats.stackexchange.com/a/78775/218516)
val <- df$Date_Diff[df$Species == "Artemisia filifolia"]
dist.fun <- approxfun(density(val))
4.采样
(sample_n()
自 dplyr 1.0.0
. 以来已被 slice_sample()
取代)
df2 <- df %>%
group_by(Species) %>%
slice_sample(n = 26, weight_by = dist.fun(Date_Diff)) %>%
ungroup()
5.检查
df2 %>% count(Species)
# Species n
# <chr> <int>
# 1 Adenostoma fasciculatum 26
# 2 Artemisia filifolia 26
# 3 Eriogonum fasciculatum 26
# 4 Tamarix L. 26
我正在尝试从数据框中采样,但条件是样本代表某个标准的分布(在我的例子中。 数据框的结构如下:
df <- data.frame(Locaton = c(A, B, B, B, C, C, ...),
Veg_Species = c(X, Y, Z, Z, Z, Z...),
Date_Diff = c(2, 5, 2, 0, 4, 4...))
重要的是要知道,Veg_Species
的数量不同。这意味着 X
出现了 25 次,例如 Y
45 次和 Z
78 次。现在我想根据最小样本 Date_Diff
的分布从不同的 Veg_Species
中抽样。在那种情况下,这意味着根据 X
.
Date_diff
分布从每个物种中抽样
我认为我可以用 dplyr
:
sample.species <- df %>% filter(Veg_Species == 'Z') %>% sample_n(25, replace = TRUE)
但这显然只是从名称为 Z
的所有 Veg_Species
中随机抽样。
我怎样才能把分布也考虑进去?
有关更详细的示例,请单击 here。
在我看来,您想对数据集进行采样,但要保持 X 子集中存在的 Date_diff
分布。
首先您需要确定 X 子集中存在什么。我做了一些看起来像你的假数据:
set.seed(123)
df <- data.frame(Location = sample(LETTERS[1:3], 148, replace = TRUE),
Veg_Species = c(rep("X", 25), rep("Y", 45), rep("Z", 78)),
Date_Diff = trunc(runif(148, 0, 10)))
现在,我们需要为 Veg_Species = X
分配 Date_Diff
。我们可以用 dplyr
:
library(dplyr)
x_dist <- df %>%
filter(Veg_Species == "X") %>%
group_by(Date_Diff) %>%
summarize(count = n())
x_dist
A tibble: 8 x 2
Date_Diff count
<dbl> <int>
1 1 2
2 2 6
3 3 5
4 4 3
5 5 3
6 6 2
7 7 2
8 8 2
现在我们过滤原始数据,nest_by(Date_Diff)
并通过x_dist
中的count
对每个data
进行采样。
set.seed(345)
df_sample <- df %>%
semi_join(x_dist) %>% # Remove all rows with Date_Diff not in x_dist
nest_by(Date_Diff) %>%
inner_join(x_dist) %>%
mutate(data = list(data[sample(1:nrow(data), # sampling the data
size = count,
replace = TRUE),])) %>%
summarize(data) %>% # unnesting the data
select(Location, veg_Species,
Date_Diff, -count) # reordering columns and removing count
df_sample
# A tibble: 25 x 3
# Groups: Date_Diff [8]
Location Veg_Species Date_Diff
<chr> <chr> <dbl>
1 C Z 1
2 A Z 1
3 A Y 2
4 C Z 2
5 B X 2
6 B Z 2
7 B X 2
8 B X 2
9 A Y 3
10 A X 3
# ... with 15 more rows
sample()
中的参数 prob=
是每个样本元素的权重向量。我的想法是使用每行的索引和权重向量进行采样。这将保留分布。
sample_by_distribution <- function(df, dist_weights_col, n, replace=FALSE) {
sampled_indexes <- sample(x=1:nrow(df), size=n, replace=replace, prob = df[, dist_weights_col])
df[sampled_indexes,]
}
通过考虑您案例中的分布权重进行抽样:
sample_df <- sample_by_distribution(df, "Date_Diff", 25, replace=FALSE)
这将对 df
的 25 行进行采样,而每行的概率都在“Date_Diff”列之后。因此,“Veg_Species”的分布也应该保留。
也许您可以尝试对 Date_Diff
的分布进行核密度估计。
1.数据和包
df <- read.csv("http://www.sharecsv.com/dl/2a26bf2c69bfd76e8ddcecd1c3739a31/ex.csv", row.names = 1)
library(dplyr)
2。找到最小的物种
df %>% count(Species)
# Species n
# 1 Adenostoma fasciculatum 95
# 2 Artemisia filifolia 26
# 3 Eriogonum fasciculatum 41
# 4 Tamarix L. 27
3。分布和线性插值的核密度估计
(参考:https://stats.stackexchange.com/a/78775/218516)
val <- df$Date_Diff[df$Species == "Artemisia filifolia"]
dist.fun <- approxfun(density(val))
4.采样
(sample_n()
自 dplyr 1.0.0
. 以来已被 slice_sample()
取代)
df2 <- df %>%
group_by(Species) %>%
slice_sample(n = 26, weight_by = dist.fun(Date_Diff)) %>%
ungroup()
5.检查
df2 %>% count(Species)
# Species n
# <chr> <int>
# 1 Adenostoma fasciculatum 26
# 2 Artemisia filifolia 26
# 3 Eriogonum fasciculatum 26
# 4 Tamarix L. 26