首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >用自然递减的数字创建模拟数据

用自然递减的数字创建模拟数据
EN

Stack Overflow用户
提问于 2018-02-20 11:22:46
回答 3查看 46关注 0票数 0

我想创建随机模拟数据,如下所示。

代码语言:javascript
复制
__ID__|__Amount__
  1        20
  1        14
  1         9
  1         3
  2        11
  2         5
  2         2

从随机数开始,但是具有相同ID的第二个数字应该小于第一个数字,并且第三个数字必须小于第二个数字。开始的最大数量应该是20。

EN

回答 3

Stack Overflow用户

发布于 2018-02-20 13:55:46

您可以使用tidyverse首先创建数据,然后根据需要对其进行排序:

代码语言:javascript
复制
set.seed(0)
df <- data.frame(id = rep(1:3,10), amt = sample(1:20, 30, replace = TRUE))

df %>%
  group_by(id) %>%
  arrange(id, desc(amt))
票数 1
EN

Stack Overflow用户

发布于 2018-02-20 12:49:22

这是一个棘手的问题,如果您希望Amount列是真正的随机值,您可以使用递归调用来递归地使用sample

代码语言:javascript
复制
## Recursively sampling from a uniform distribution
recursive.sample <- function(start, end, length, results = NA, counter =0) {

    ## To enter the recursion, counter must be smaller than the length out
    ## and the last result must be smaller than the starting point (except the firs time)
    if(counter < length && ifelse(counter != 0, results[counter] > start, TRUE)){

        ## Increment the counter
        counter <- counter + 1

        ## Sample between start and the last result or the start and the end of the vector
        results[counter] <- ifelse(counter != 1, sample(start:results[counter-1], 1), sample(start:end, 1))

        ## Recursive call
        return(recursive.sample(start = start, end = end, length = length, results = results, counter = counter))

    } else {

        ## Exit the recursion
        return(results)
    }
}

## Example
set.seed(0)
recursive.sample(start = 1, end = 20, length = 3, results = NA, counter = 0)
#[1] 18  5  2

或者(以更简单的方式),您可以使用sort(sample())

代码语言:javascript
复制
set.seed(0)
sort(sample(1:20, 3), decreasing = TRUE)
#[1] 18  7  6

请注意,由于在递归函数中采样较高值的概率较低,因此结果不同。

然后,您可以使用您选择的函数轻松创建表,如下所示:

代码语言:javascript
复制
set.seed(123)
## The ID column
ID <- c(rep(1, 4), rep(2,3))
## The Amount column
Amount <- c(recursive.sample(1, 20, 4, NA, 0), recursive.sample(1, 11, 3, NA, 0))
## The table
cbind(ID, Amount)
#     ID Amount
#[1,]  1     18
#[2,]  1      5
#[3,]  1      2
#[4,]  1      2
#[5,]  2     10
#[6,]  2      3
#[7,]  2      3

或者,再次使用简单的sort(sample())函数,以获得更高的选择较大数字的概率。

票数 0
EN

Stack Overflow用户

发布于 2018-02-20 21:37:49

两种方法,一种使用dplyr,另一种仅使用基本R函数。这些与前面的两个解决方案略有不同。

我使用了排序ID列,但这不是必需的。

方法1

代码语言:javascript
复制
rm(list = ls())
set.seed(1)
df <- data.frame(ID = rep(1:3, each = 5))

df %>% group_by(ID) %>% 
  mutate(Amount = sort(sample(1 : 20, n(), replace = T), decreasing = TRUE))

方法2

代码语言:javascript
复制
rm(list = ls())
set.seed(1)
df <- data.frame(ID = rep(1:3, each = 5))
df$Amount <- NA

uniq_ID <- unique(df$ID)
index_lst <- lapply(uniq_ID, function(x) which(df$ID == x))
res <- lapply(index_lst, function(x) sort(sample(1 : 20, length(x)), 
                                   decreasing = TRUE))
df$Amount[unlist(index_lst)] <- unlist(res)

方法2.5

这比第二种方法更复杂。

代码语言:javascript
复制
rm(list = ls())
set.seed(1)
df <- data.frame(ID = rep(1:3, each = 5))
df$Amount <- NA

tab <- as.data.frame(table(df$ID))
lapply(1 : nrow(tab), function(x) df$Amount[which(df$ID == tab$Var1[x])] <<-
         sort(sample(1 : 20, tab$Freq[x]), decreasing = TRUE))
票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/48877375

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档