【问题标题】:Column-wise computation逐列计算
【发布时间】:2021-11-30 20:51:24
【问题描述】:

我正在尝试按列计算。目标是计算一个指数 (IX) 对于每个玩家 (r001,r002,r003),在每个游戏回合(行)中。

#the data frame looks like this: 
df <- data.frame(gameround= c("1_1", "1_2", "1_3"),
  r001 = c(3,5,4), r002 = c(2,3,5), r003 = c(1,2,2), weight001=c(0.7,0.8,0.7), 
                 weight002 = c(0.6,0.1,0.6), weight003=c(0.2,0.7,0.2), 
                 FORMULA = c("PosdownNegUp", "NegdownPosUp", "PosdownNegUp"), 
                IXsum = NA)

#There are two different formulas:
#FORMULA PosdownNegUp:
#if r001 is 1, take weight001*1. 
#if r001 is 2, take  weight001*0.5. 
#if r001 is 4, take weight001*-0.5. 
#if r001 is 5, take weight001*-1. 
#IXSUM = repeat for every r00 and take the sum per gameround. 

#FORMULA NegdownPosUp: 
#if r001 is 1, take weight001*-1. 
#If r001 is 2, take weight001*-0.5.
#if r001 is 4, take weight001*0.5. 
#if r001 is 5, take weight001*1. 
#IXSUM = repeat for every r00 and take the sum per gameround. 

#Player scores of 3 or 0 should not be included in the IXsum calculation.

#the result should look like this: 
df

#  gameround r001 r002 r003  weight001  weight002 weight003     FORMULA      IXsum
#       1_1    3    2    1       0.7       0.6       0.2     PosdownNegUp     0.5  # = (0.6*0.5)+(0.2*1)
#       1_2    5    3    2       0.8       0.1       0.7     NegdownPosUp     0.45 # (0.8*1)+(0.7*-0.5)
#       1_3    4    5    2       0.7       0.6       0.2     PosdownNegUp    -0.85 # = (0.7*-0.5)+(0.6*-1)+(0.2*0.5)    

如果有人可以帮助我,我将非常感激!

【问题讨论】:

  • 将宽转长,然后计算。

标签: r loops dplyr tidyverse calculated-columns


【解决方案1】:

看起来像 dplyr::case_when() 结合一些 rlang 的东西

for(i in  1:3){

  # define symbols for the variables
  variable <- paste0("r00", i)
  variable <- rlang::sym(variable)

  tempvariable <- paste0("IXsum", i)
  tempvariable <- rlang::sym(tempvariable)

  formulavariable <- paste0("weight00", i)
  formulavariable <- rlang::sym(formulavariable)


df <- df %>% dplyr::mutate(
  # notice that we use the 'bang bang' operator (!!) to tell R that we use symbols, and use ':=' to assign to a variable instead of just '='
  !!tempvariable := dplyr::case_when(
    FORMULA == "PosdownNegUp" & !!variable == 1 ~ !!formulavariable,
    FORMULA == "PosdownNegUp" & !!variable == 2 ~ !!formulavariable*0.5,
    FORMULA == "PosdownNegUp" & !!variable == 4 ~ !!formulavariable*-0.5,
    FORMULA == "PosdownNegUp" & !!variable == 5 ~ !!formulavariable*-1,
    FORMULA == "NegdownPosUp" & !!variable == 1 ~ !!formulavariable*-1,
    FORMULA == "NegdownPosUp" & !!variable == 2 ~ !!formulavariable*-0.5,
    FORMULA == "NegdownPosUp" & !!variable == 4 ~ !!formulavariable*0.5,
    FORMULA == "NegdownPosUp" & !!variable == 5 ~ !!formulavariable*1))

}

这会导致:

df

  > gameround  r001  r002  r003 weight001 weight002 weight003 FORMULA IXsum IXsum1 IXsum2 IXsum3
  <chr>     <dbl> <dbl> <dbl>     <dbl>     <dbl>     <dbl> <chr>        <lgl>  <dbl>  <dbl>  <dbl>
1 1_1           3     2     1       0.7       0.6       0.2 PosdownNegUp NA     NA       0.3   0.2 
2 1_2           5     3     2       0.8       0.1       0.7 NegdownPosUp NA      0.8    NA    -0.35
3 1_3           4     5     2       0.7       0.6       0.2 PosdownNegUp NA     -0.35   -0.6   0.1 

最后可以总结一下临时列

df %>% dplyr::mutate(
  IXsum = ifelse(is.na(IXsum1), 0,IXsum1)+ifelse(is.na(IXsum2), 
0,IXsum2)+ifelse(is.na(IXsum3), 0,IXsum3))
%>% 
dplyr::select(-IXsum1, -IXsum2, -IXsum3)


gameround  r001  r002  r003 weight001 weight002 weight003 FORMULA      IXsum
  <chr>     <dbl> <dbl> <dbl>     <dbl>     <dbl>     <dbl> <chr>        <dbl>
1 1_1           3     2     1       0.7       0.6       0.2 PosdownNegUp  0.5 
2 1_2           5     3     2       0.8       0.1       0.7 NegdownPosUp  0.45
3 1_3           4     5     2       0.7       0.6       0.2 PosdownNegUp -0.85

【讨论】:

  • 谢谢!但是,INXsum 应该对不同玩家进行这些计算的总和,因此 r002、r003 也应该包括在内。
  • r001, r002, r003 是否有'just'?, r001 = 3 时的公式是什么?
  • 不,实际上有 8 个玩家 (r00's)。 r001=3 & r001=0 不包含在总和中,因此您可以跳过这些。
  • 你太棒了!感谢您的努力:))))
【解决方案2】:

wide-to-long 转换数据,然后按组计算 - gameround。这将扩展到任意数量的玩家:

library(data.table)

#convert to data.table
setDT(df)

# wide-to-long, then compute
melt(df, id.vars = c("gameround", "FORMULA", "IXsum"), 
          measure.vars = patterns("^r", "^weight"), 
          value.name = c("rr", "ww") 
     )[,.(IXsum = sum(ww * 
                        ifelse(FORMULA == "PosdownNegUp", -1,
                               ifelse(FORMULA == "NegdownPosUp", 1)) *
                        ifelse(rr %% 2 == 0, 0.5, 1))), by = "gameround"]
     
#    gameround IXsum
# 1:       1_1 -1.20
# 2:       1_2  1.25
# 3:       1_3 -1.05

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2022-11-30
    • 1970-01-01
    • 1970-01-01
    • 2013-04-08
    • 1970-01-01
    • 2021-10-17
    相关资源
    最近更新 更多