r - 如何根据 data.frame 中的变量引用列表?

标签 r

我有一个带有 emp_id 的简单表格和 job_code .我想返回正确的 payout基于 job_code
我已经用嵌套的 ifelse 管理了这个,但是如果我有更多的怎么办 job_code的?

library(dplyr)
set.seed(1)

emp_id   <- round(rnorm(100, 500000, 10000))
job_code <- sample(c('a', 'b', 'c'), 100, replace = TRUE)
result   <- sample(c(1,2,3,4), 100, replace = TRUE)

df <- data.frame(emp_id = emp_id, job_code = job_code, result = result)

job_a <- c(0, 500, 1000, 5000)
job_b <- c(0, 200, 500, 750)
job_c <- c(0, 250, 750, 1000)

# Works but sucky
df %>% mutate(payout = ifelse(job_code == 'a', job_a[result],
  ifelse(job_code == 'b', job_b[result],
    job_c[result])))

dput若你宁可:
structure(list(emp_id = c(493735, 501836, 491644, 515953, 503295, 
491795, 504874, 507383, 505758, 496946, 515118, 503898, 493788, 
477853, 511249, 499551, 499838, 509438, 508212, 505939, 509190, 
507821, 500746, 480106, 506198, 499439, 498442, 485292, 495218, 
504179, 513587, 498972, 503877, 499462, 486229, 495850, 496057, 
499407, 511000, 507632, 498355, 497466, 506970, 505567, 493112, 
492925, 503646, 507685, 498877, 508811, 503981, 493880, 503411, 
488706, 514330, 519804, 496328, 489559, 505697, 498649, 524016, 
499608, 506897, 500280, 492567, 501888, 481950, 514656, 501533, 
521726, 504755, 492901, 506107, 490659, 487464, 502914, 495567, 
500011, 500743, 494105, 494313, 498648, 511781, 484764, 505939, 
503330, 510631, 496958, 503700, 502671, 494575, 512079, 511604, 
507002, 515868, 505585, 487234, 494267, 487754, 495266), job_code = structure(c(1L, 
1L, 2L, 1L, 1L, 2L, 2L, 1L, 1L, 3L, 3L, 1L, 3L, 3L, 3L, 1L, 2L, 
3L, 3L, 2L, 1L, 1L, 1L, 2L, 3L, 2L, 1L, 1L, 2L, 3L, 2L, 1L, 2L, 
2L, 2L, 3L, 3L, 2L, 2L, 2L, 1L, 2L, 3L, 1L, 2L, 1L, 2L, 1L, 2L, 
3L, 3L, 3L, 2L, 2L, 2L, 1L, 1L, 2L, 2L, 3L, 2L, 1L, 1L, 3L, 3L, 
1L, 1L, 3L, 2L, 1L, 1L, 1L, 2L, 1L, 1L, 1L, 1L, 1L, 2L, 3L, 1L, 
2L, 3L, 2L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 3L, 1L, 2L, 3L, 1L, 
1L, 1L, 3L), .Label = c("a", "b", "c"), class = "factor"), result = c(3, 
1, 2, 2, 2, 4, 1, 4, 1, 2, 1, 1, 4, 3, 2, 2, 1, 2, 4, 3, 3, 2, 
2, 4, 4, 4, 4, 4, 2, 4, 4, 2, 2, 4, 1, 2, 2, 1, 3, 4, 4, 1, 3, 
2, 3, 2, 2, 1, 2, 3, 2, 1, 4, 2, 4, 2, 4, 1, 4, 2, 1, 2, 4, 2, 
3, 4, 1, 3, 3, 2, 2, 3, 4, 1, 1, 2, 2, 4, 1, 2, 2, 3, 3, 4, 1, 
1, 4, 4, 1, 4, 1, 1, 4, 3, 1, 2, 3, 2, 2, 1)), .Names = c("emp_id", 
"job_code", "result"), row.names = c(NA, -100L), class = "data.frame")

理想情况下,我想做的是在 data.frame 中有支出,但不确定如何正确引用它:
job_payouts <- data.frame(a = job_a, b = job_b, c = job_c)
# Won't work...
df %>% mutate(payout = job_payouts$job_code[result])

最佳答案

这可以通过在基数 R 中进行矩阵索引的超酷方法来实现,该方法非常快速和高效。

# build jobs payout lookup matrix, by hand (see edit below for an extension)
jobs <- rbind(job_a, job_b, job_c)

# add row names to the matrix for convenient reference
rownames(jobs) <- levels(df$job_code)

# get payout using matrix indexing
df$payout <- jobs[cbind(df$job_code, df$result)]

这返回
# print out first 6 observations
head(df)
  emp_id job_code result payout
1 493735        a      3   1000
2 501836        a      1      0
3 491644        b      2    200
4 515953        a      2    500
5 503295        a      2    500
6 491795        b      4    750

# print out jobs matrix for comparison
jobs
  [,1] [,2] [,3] [,4]
a    0  500 1000 5000
b    0  200  500  750
c    0  250  750 1000

有几个细节值得一提。
  • data.frame函数转换job_code字符向量,使得df$job_code是一个因子变量,其中标签与自然数 1、2、3... "到 2,"c"到 3。您可以使用 levels函数来查找因子变量的顺序并按照该模板构建工作矩阵。
  • 工作矩阵用作查找表。它的构造使得这些整数指的是作业矩阵的行号。然后,列可以是子集,就像您对原始支出向量所做的一样。
  • cbind(df$job_code, df$result)nrow(df) 形成 2 (100) 矩阵用于查找 nrow(df)使用矩阵索引从工作矩阵中为每个员工的支付值。 R intro manual有一个关于矩阵索引的很好的介绍部分,其他详细信息可以在 help("[") 中找到。 .


  • 编辑:自动构建查找矩阵

    在对此答案的评论中,OP 表示担心手动构建查找矩阵(我称之为“作业”)会很乏味并且容易出错。为了解决这些有效的问题,我们可以对 mget 使用一个有点晦涩的论点。函数,“ifnotfound”。这个参数允许我们控制列表元素的输出 mget当它们存在于名称向量中但不存在于环境中时返回。

    在评论中,我建议使用 NA在下面的评论中填写缺失的级别。我们可以通过使用 NA 来扩展它作为“ifnotfound”的输入。

    假设 df$job_code是一个因子,其级别为“a”、“aa”、“b”和“c”。然后我们构建查找矩阵如下:
    # build vector for example, the actual code, using levels(), follows as a comment
    job_codes <- c("a", "aa", "b", "c") # job_codes <- levels(df$jobcodes)
    
    # get ordered list of payouts, with NA for missing payouts
    payoutList <- mget(paste0("job_", job_codes), ifnotfound=NA)
    

    它返回一个命名列表。
    payoutList
    $job_a
    [1]    0  500 1000 5000
    
    $job_aa
    [1] NA
    
    $job_b
    [1]   0 200 500 750
    
    $job_c
    [1]    0  250  750 1000
    

    请注意 payoutList$job_aa是单个 NA。现在,从这个列表构建矩阵。
    # build lookup matrix using do.call() and rbind()
    jobs.lookupMat <- do.call(rbind, payoutList)
    
    jobs.lookupMat
           [,1] [,2] [,3] [,4]
    job_a     0  500 1000 5000
    job_aa   NA   NA   NA   NA
    job_b     0  200  500  750
    job_c     0  250  750 1000
    

    矩阵的行根据因子 df$job_code 的级别正确排序,方便地命名,和 NA s 在没有支出的地方填写行。

    关于r - 如何根据 data.frame 中的变量引用列表?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/39235882/

    相关文章:

    r - 逐行融化数据框

    r - .Rnw 文件中的 Perl : the 'tilde' character

    r - 在 r ggplot 中使用 scale_color_binned 时限制和中断值的自定义标签

    r - 排序和呈现我的数据的问题 - tapply 和图形问题

    r - 如何让用户在 writecsv 中选择输出文件名

    sql - 将 R 连接到 postgreSQL 数据库

    r - 根据度数排序节点并使用 igraph 在 R 中操作

    r - 如何快速将数据框中的时间列分组为间隔?

    r - dplyr::filter() 的意外行为

    r - 禁用图例双击事件