【问题标题】:Ho to run a function (many times) that changes variable (tibble) in global env何运行一个函数(多次)改变全局环境中的变量(tibble)
【发布时间】:2020-07-13 02:17:55
【问题描述】:

我是 R 的新手,所以请耐心等待...欢迎提供建议。

我的目标是创建包含“全名”(一个人,可能有 2 到 4 个名字)和他/她的性别的 tibble。我必须从包含典型男性和女性名字的小标题开始。

下面我给出一个最小的工作示例。

我的问题:我可以多次调用get_name()(在 10.000 for 循环中!!)并得到正确答案。但是,我一直在寻找一种更“优雅”的方式。 replicate() 不幸地返回了一个向量......这使它无法使用。

我的疑虑:我知道我有一些(很少......对!!)问题,比如 if 声明,每次都会评估(这是多余的),但我没有找到其他方法做。有什么建议吗?

也欢迎任何其他关于代码结构的建议。

非常感谢您的帮助。

# Dummy name list
unit_names <- tribble(
  ~Women, ~Man,
  "fem1", "male1",
  "fem2", "male2", 
  "fem3", "male3",
  "fem4", "male4",
  "fem5", "male5",
  "fem6", NA,
  "fem7", NA
)

set.seed(12345) # seed for test

# Create a tibble with the full names
full_name <- tibble("Full Name" = character(), "Gender" = character() )

get_name <- function() {
  # Get the Number of 'Unit-names' to compose a 'Full-name'
  nbr_names <- sample(2:4, 1, replace = TRUE)
  # Randomize the Gender
  gender  <- sample(c("Women", "Man"), 1, replace = TRUE)
  if (gender == "Women") {
    lim_names <- sum( !is.na(unit_names$"Women"))
  } else {
    lim_names <- sum( !is.na(unit_names$"Man"))
  }

  # Sample the Fem/Man List names (may have duplicate)
  sample(unlist(unit_names[1:lim_names, gender]), nbr_names, replace = TRUE) %>%
    # Form a Full-name
    paste ( . , collapse = " ") %>%
    # Add it to the tibble (INCLUDE the Gender)
    add_row(full_name, "Full Name" = . , "Gender" = gender)
}

# How can I make 10k of this?
full_name <- get_name()

【问题讨论】:

    标签: r function tibble


    【解决方案1】:

    在 Konrad Rudolph 的一点点帮助下,我正在寻找以下优雅(和矢量化......并且快速)的解决方案。 map2 做了必要的把戏。

    如果有人需要,这里是完整的工作示例: (附注:我保留了从 tibble 到 list 的初始转换,因为数据作为 tibble 到达我...)

    再次感谢康拉德。

    # Dummy name list
    unit_names <- tribble(
      ~Women, ~Men,
      "fem1", "male1",
      "fem2", "male2", 
      "fem3", "male3",
      "fem4", "male4",
      "fem5", "male5",
      "fem6", NA,
      "fem7", NA
    )
    name_list <- list(
      Women = unit_names$Women[!is.na(unit_names$Women)],
      Men = unit_names$Men[!is.na(unit_names$Men)]
    )
    
    generate_names = function (n, name_list) {
      name_length = sample(2 : 4, n, replace = TRUE)
      genders = sample(c('Women', 'Men'), n, replace = TRUE)
      #names = lapply(name_list[genders], sample,  name_length) %>%
      names = map2(name_list[genders], name_length, sample) %>%
        lapply(paste, collapse = ' ') %>%
        unlist()
      tibble(`Full name` = names, Gender = genders)
    }
    
    full_name <- generate_names(10000, name_list)
    

    【讨论】:

      【解决方案2】:

      如果你将比1 更大的数字传递给sample,这个问题就更容易向量化了。

      目前让您的问题变得更加困难的一件事是您的 unit_names 表的布局:您实际上将男性和女性的名字视为单独配对,但显然不是:因此它们不应该出现在同一张桌子。使用两个向量的列表,例如:

      unit_names = list(
          Women = c("fem1", "fem2", "fem3", "fem4", "fem5", "fem6", "fem7"),
          Men = c("male1", "male2", "male3", "male4", "male5")
      )
      

      然后,您可以随意生成随机名称:

      generate_names = function (n, unit_names) {
          name_length = sample(2 : 4, n, replace = TRUE)
          genders = sample(c('Women', 'Men'), n, replace = TRUE)
          names = Map(sample, unit_names[genders], name_length, replace = TRUE) %>%
              lapply(paste, collapse = ' ') %>%
              unlist()
          tibble(`Full name` = names, Gender = genders)
      }
      

      关于样式的说明,与您的函数不同,上面不使用任何全局变量。此外,不要“引用”变量名(你在unit_names$"Women"add_row 的参数中这样做)。 R 允许这样做,但这可以说是语言规范中的一个错误:这些 不是字符串,它们是变量名,让它们看起来像字符串是一种误导。毕竟,您不会引用其他变量名。您确实需要反引号引用`Full name` 列名,因为它包含一个空格。但是,使用 反引号,而不是引号,表示这是一个变量名。

      【讨论】:

      • HI Konrad,我实际上是在寻找一种矢量化解决方案(就像你提出的那个)......但每次都遇到一些小问题......就像我在你的解决方案中找到的那样:)。在第一个“lapply”中,传递给“sample”的参数是“name_length”,它是一个未正确解释的向量(即逐个值)。它使用他的长度,或者,如果您明确地将其命名为“size = name_length”,则只取第一个值。我错过了一些细节吗? (R充满了细节:()。
      • @acombo 你说得对,很好!您需要将sample 成对应用于两个向量的元素。 lapply 不能这样做,但 Map 可以。这对应于map2,如果你想使用purrr而不是base R(就像lapply对应于purrr的map)。
      【解决方案3】:

      我不是你想要得到的 100%,但如果我做对了......你是否尝试在 dplyr 使用 mutate ?例如: result= mutate(data.frame, concated_column = paste(column1, column2, column3, column4, sep = '_'))

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2020-06-08
        相关资源
        最近更新 更多