【问题标题】:generating a random string and doing simulation in R生成随机字符串并在 R 中进行模拟
【发布时间】:2018-09-06 07:13:36
【问题描述】:

我想创建一个长度为 50 的随机字符串,其中只有四个字符 'e'、'l'、'i'、'r',出现频率为 0.6、0.1、0.1、0.2。创建一个随机字符串后,我想做 5000 次模拟,看看每次模拟中出现“el”的比例。我使用以下命令创建了一个随机字符串:

x <- paste(sample( c('e','l','i','r'), 50, replace=TRUE, prob=c(0.6,0.1, 0.1, 0.2) ),collapse = '')

但是现在我很困惑如何进行 5000 次模拟。我用谷歌搜索我也许可以使用复制功能并用它来找到比例。但我很困惑如何在这种情况下使用它。帮助将不胜感激。

【问题讨论】:

  • 我怎样才能在每次模拟中找到“el”的比例?我是否将在每次模拟中找到“el”的次数除以字符串的总长度?

标签: r


【解决方案1】:

所以你找到了co-occurrence。如果你不paste 结果会更容易(而且更快)。我会调整我对链接问答的回答中定义的函数foo

set.seed(0)

## one example sample
char_tank <- c('e','l','i','r')
char_prob <- c(0.6, 0.1, 0.1, 0.2)
x <- sample(char_tank, 50, replace = TRUE, prob = char_prob)
# [1] "i" "e" "e" "e" "l" "e" "i" "l" "r" "r" "e" "e" "e" "r" "e" "r" "e" "r" "l"
#[20] "e" "r" "l" "e" "r" "e" "e" "e" "e" "e" "i" "e" "e" "e" "e" "e" "i" "r" "r"
#[39] "e" "r" "e" "i" "r" "r" "e" "e" "r" "e" "e" "r"

## adapted from function `foo` from https://stackoverflow.com/a/51695793/4891738
## the function is shorter because you just want to find not to remove matches
count_co_occurrence <- function (xm, xs) {
  nm <- length(xm)
  ns <- length(xs)
  shift_ind <- outer(0:(ns - 1), 1:(nm - ns + 1), "+")
  d <- xm[shift_ind] == xs
  sum(.colSums(d, ns, length(d) / ns) == ns)
  }

count_co_occurrence(x, c('e', 'l'))
#[1] 1

在这种情况下,您会看到 x[4:5] 是匹配项。


直接使用replicate + lapply / sapply / vapply 重复上述操作即可。

## just do 10 simulations as a small example
set.seed(0)
xx <- replicate(10, sample(char_tank, 50, replace = TRUE, prob = char_prob),
                simplify = FALSE)
yy <- vapply(xx, count_co_occurrence, xs = c('e', 'l'), 0L)
# [1] 1 1 4 1 2 2 4 4 5 5

我不确定您如何定义共现的“比例”。在这种情况下是yy / (50 - (2 - 1))吗?

【讨论】:

    【解决方案2】:

    从您的代码开始:

    set.seed(2)
    x <- paste(sample( c('e','l','i','r'), 50, replace=TRUE, prob=c(0.6,0.1, 0.1, 0.2) ),collapse = '')
    x
    # [1] "ereelleieeeereeileeereieeeeeleeeiieriereleeelrleei"
    

    我们可以很容易地复制这个:

    set.seed(2)
    xmany <- replicate(5000, paste(sample( c('e','l','i','r'), 50, replace=TRUE, prob=c(0.6,0.1, 0.1, 0.2) ),collapse = ''))
    head(xmany)
    # [1] "ereelleieeeereeileeereieeeeeleeeiieriereleeelrleei"
    #4#       ^                       ^           ^   ^
    # [2] "eerleirlrrrireieeeeeeeeeereieeereeeilereleeeeeeeee"
    #1#                                           ^
    # [3] "eelieeieeeereeiiieleeeliereereelelereieeeereerreee"
    #5#     ^               ^   ^        ^ ^
    # [4] "eelereieeeilerereleeleeiereerelelreiereeeeleeeeeee"
    #6#     ^              ^  ^         ^ ^         ^
    # [5] "irrleieeeeleirleeeeeeleerilerireieieeeeeieerlleeee"
    #2#             ^          ^
    # [6] "reeereeeerrereirerieiliereleeeelrreleereeerereeeee"
    #3#                             ^    ^   ^
    

    我添加了文本以突出显示每个字符串中出现的"el"

    如果您需要每个字符串中"el" 的出现次数,那么(所有内容都没有head):

    ispos <- function(a) a > 0
    head( lengths(Filter(ispos, gregexpr("el", xmany))) )
    # [1] 4 1 5 6 2 3
    

    注意:我创建了ispos 函数,因为gregexpr 将在没有匹配时返回-1,这使得返回的向量长度保持在1 或更多。因此,通过去除负面因素,我们得到了诚实的回报。 (我本可以使用regmatches(gregexpr(...),xmany),但这似乎比获得出现次数所需的工作量要多得多。)

    如果你需要它的频率表:

    table( lengths(Filter(ispos, gregexpr("el", xmany))) )
    #    0    1    2    3    4    5    6    7    8    9 
    # 9701  891 1145 1241  936  459  178   69   16    1 
    

    【讨论】:

      猜你喜欢
      • 2014-03-11
      • 1970-01-01
      • 2014-02-09
      • 2017-08-01
      • 2011-06-30
      • 2010-11-23
      • 2016-07-31
      相关资源
      最近更新 更多