r - 变长 df 二次采样函数 r

标签 r function dplyr subset subsampling

我需要编写一个函数,涉及用变量n bins 子集 df。例如,如果 n 为 2,则在两个 bin 中对 df 进行多次二次采样(从前半部分开始,然后从后半部分开始)。如果 n 为 3,则在 3 个 bin 中进行子采样(第一个 1/3、第二个 1/3、第三个 1/3)。到目前为止,我一直在手动对不同长度的 n 执行此操作,并且我知道一定有更好的方法来执行此操作。我想将其写入一个以 n 作为输入的函数,但到目前为止我还无法使其工作。代码如下。

# create df
df <- data.frame(year = c(1:46), 
                 sample = seq(from=10,to=30,length.out = 46) + rnorm(46,mean=0,sd=2) )
# real df has some NAs, so we'll add some here
df[c(20,32),2] <- NA

这个df是46年的采样。我想假装不是 46 个样本,而是只取了 2 个样本,但在上半年随机一年 (1:23),在下半年随机一年 (24:46)。

# to subset in 2 groups, say, 200 times
# I'll make a df of elements to sample
samplelist <- data.frame(firstsample = sample(1:(nrow(df)/2),200,replace = T), # first sample in first half of vector
                         secondsample = sample((nrow(df)/2):nrow(df),200, replace = T) )# second sample in second half of vector
samplelist <- as.matrix(samplelist)


# start a df to add to
plot_df <- df %>% mutate(first='all',
                               second = 'all',
                               group='full')

# fill the df using coords from expand.grid
for(i in 1:nrow(samplelist)){

  plot_df <<- rbind(plot_df,
                          df[samplelist[i,] , ]   %>% 
                            mutate(
                              first = samplelist[i,1],
                              second = samplelist[i,2],
                              group = i
                            )) 
  print(i)
}

(如果我们可以让它跳过“NA”样本年的样本,那就太好了)。

所以,如果我想获得三个点而不是两个点,我会像这样重复这个过程:

# to subset in 3 groups 200 times
# I'll make a df of elements to sample
samplelist <- data.frame(firstsample = sample(1:(nrow(df)/3),200,replace = T), # first sample in first 1/3
                         secondsample = sample(round(nrow(df)/3):round(nrow(df)*(2/3)),200, replace = T),  # second sample in second 1/3
                         thirdsample = sample(round(nrow(df)*(2/3)):nrow(df), 200, replace=T) # third sample in last 1/3
                         )
samplelist <- as.matrix(samplelist)

# start a df to add to
plot_df <- df %>% mutate(first='all',
                         second = 'all',
                         third = 'all',
                         group='full')

# fill the df using coords from expand.grid
for(i in 1:nrow(samplelist)){

  plot_df <<- rbind(plot_df,
                    df[samplelist[i,] , ]   %>% 
                      mutate(
                        first = samplelist[i,1],
                        second = samplelist[i,2],
                        third = samplelist[i,3],
                        group = i
                      )) 
  print(i)
}

但是,我想多次执行此操作,采样最多约 20 次(因此在 20 个容器中),因此这种手动方法不可持续。你能帮我写一个函数来表示“从 n 个箱子中选取一个样本 x 次”吗?

顺便说一句,这是我用完整的 df 绘制的图:

plot_df %>%
  ggplot(aes(x=year,y=sample)) +

  geom_point(color="grey40") +

  stat_smooth(geom="line",
              method = "lm",
              alpha=.3,
              aes(color=group,
                  group=group),
              se=F,
              show.legend = F) +
  geom_line(color="grey40") +


  geom_smooth(data = plot_df %>% filter(group %in% c("full")),
              method = "lm",
              alpha=.7,
              color="black",
              size=2,
              #se=F,
              # fill="grey40
              show.legend = F
  ) +
  theme_classic()

最佳答案

如果我没理解错的话,下面的函数将你的 df 分成 n 个容器,从每个容器中抽取 x 个样本,然后将结果放回到 df 的列中:

library(tidyverse)

set.seed(42)

df <- data.frame(year = c(1:46), 
                 sample = seq(from=10,to=30,length.out = 46) + rnorm(46,mean=0,sd=2) )

get_df_sample <- function(df, n, x) {
  df %>% 
    # bin df in n bins of (approx.) equal length
    mutate(bin = ggplot2::cut_number(seq_len(nrow(.)), n, labels = seq_len(n))) %>% 
    # split by bin
    split(.$bin) %>%
    # sample x times from each bin
    map(~ .x[sample(seq_len(nrow(.x)), x, replace = TRUE),]) %>% 
    # keep only column "sample"
    map(~ select(.x, sample)) %>% 
    # Rename: Add number of df-bin from which sample is drawn
    imap(~ rename(.x, !!sym(paste0("sample_", .y)) := sample)) %>%
    # bind
    bind_cols() %>% 
    # Add group = rownames
    rownames_to_column(var = "group")
}
get_df_sample(df, 3, 200) %>% 
  head()
#>   sample_1 sample_2 sample_3 group
#> 1 12.58631 18.27561 24.74263     1
#> 2 19.46218 24.24423 23.44881     2
#> 3 12.92179 18.47367 27.40558     3
#> 4 15.22020 18.47367 26.29243     4
#> 5 12.58631 24.24423 24.43108     5
#> 6 19.46218 23.36464 27.40558     6

reprex package于2020年3月24日创建(v0.3.0)

关于r - 变长 df 二次采样函数 r,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/60829944/

相关文章:

r - 根据各种其他列值中的值创建新列 - 使用 R

r - 如何根据左相邻列中的值替换多列中的值

R - 基于多个条件匹配来自 2 个数据帧的值(当查找 ID 的顺序是随机的时)

R 包失败 devtools::check,因为 "could not find function"即使函数是在 NAMESPACE 中导入的

r - 从词向量到文档向量[text2vec]

r - 如何在 dplyr 中定义函数? - 添加卡方检验的结果

C : error: expected expression before âSRT_ControleComplet_Sâ

r - 如何在 R 中计算滚动引导值和置信区间

java - 让函数返回 JLabel 并将其添加到 JFrame

r - 使用 dplyr 按多个行和列匹配对数据帧进行子集化