【问题标题】:Comp. Efficent way of resetting sequence if condition met ( R )比较。条件满足时重置序列的有效方法(R)
【发布时间】:2015-09-13 22:24:01
【问题描述】:

问题:

如果满足条件(主题更改),我想重置 (1,2) 序列。
我有forif 循环可以做到这一点,但不出所料,这种方法非常慢。 对于更有效的方法有什么建议(例如,涉及 apply 系列)?

当前:

  subj odd_even
    a         
    a         
    a         
    b         
    b         
    b         
    b         
    c         
    c         
    c         

目标:

  subj odd_even
    a      1   
    a      2   
    a      1   
    b      1   
    b      2   
    b      1   
    b      2   
    c      1   
    c      2   
    c      1   

df = data.frame( subj = c("a","a","a","b","b","b","b", "c","c","c"), odd_even = "" )

【问题讨论】:

  • 这是一种笨拙的方法,但您可以按主题分离 df,为每个 df 创建 odd_even,然后将 rbind 重新组合在一起

标签: r data-manipulation


【解决方案1】:

这是另一种笨拙的方法:

df$odd_even <- 2L - ave(as.integer(df$s),df$s,FUN=seq_along) %% 2L

ave 在每个组中创建一个计数器。该计数器是我们正在奇数与偶数测试的结果。

【讨论】:

  • 我使用ave()的方式略有不同,但在这种情况下它是一个有用的功能:ave(seq_along(df$subj), df$subj, FUN=function(x) rep(c(1,2), length.out=length(x)))
  • @MrFlick 哦,这是一个不错的方法;我忘了length.out。我不喜欢ave 要求第一个数字参数和明确的FUN=;让一切都变得痛苦。我总是需要尝试三次才能使其正常工作。
【解决方案2】:

如果 subj 稍后在数据帧中再次出现,期望的行为是什么?

如果它不会发生,这里有一个dplyr 方法:

library(dplyr)

df %>% group_by(subj) %>%
       mutate(odd_even = 2 - (row_number() %% 2))

【讨论】:

  • 我认为可以安全地假设它是按主题排序的。
  • 是的,确实如此。谢谢!
【解决方案3】:

我喜欢 sequence 函数:

df$odd_even <- 2L - sequence(table(df$subj)) %% 2L

data.table 是另一种选择:

library(data.table)
setDT(df)
df[, odd_evenDT := 2L - seq_along(.I) %% 2L, by = subj]

基准测试:

set.seed(42)
df <- data.frame(subj = sort(sample(as.character(1:1e4), 1e5, TRUE)))
DT <- data.table(df)

library(microbenchmark)
microbenchmark(roland1 = 2L - sequence(table(df$subj)) %% 2L,
           roland2 = DT[,2L - seq_along(.I) %% 2L, by = subj],
           roland3 = 2L - sequence(rle(as.integer(df$subj))$lengths) %% 2L,
           jeremy = df %>% group_by(subj) %>%
             mutate(odd_even = 2 - (row_number() %% 2)),
           frank = 2L - ave(as.integer(df$s),df$s,FUN=seq_along) %% 2L, 
           flick = ave(seq_along(df$subj), df$subj, FUN=function(x) rep(c(1,2), length.out=length(x))),
           times = 10, unit = "relative")

# Unit: relative
#     expr      min       lq      mean   median        uq      max neval
#  roland1 5.820459 5.754497 5.0368686 5.404110 4.0853039 4.847161    10
#  roland2 1.110919 1.057952 0.9840653 1.037428 0.7939004 1.176258    10
#  roland3 1.000000 1.000000 1.0000000 1.000000 1.0000000 1.000000    10
#   jeremy 5.024087 4.941366 4.3491117 4.635534 3.5144515 4.277011    10
#    frank 2.036816 1.944603 1.7809168 1.831937 1.6459597 1.607283    10
#    flick 3.655127 3.621457 3.2453089 3.473188 2.7717947 3.198285    10

【讨论】:

  • sequence 的东西非常优雅。我猜table 会按subj 的字母顺序排序,所以不仅要求subj 记录是连续的,还要在subjs 之间排序。
  • 正确。不过,如果这是一个问题,你总是可以先做df$subj &lt;- ordered(df$subj, levels = unique(df$subj))
  • 啊,没见过这个功能。我在想另一种选择是rle(as.integer(df$subj))$lengths 而不是table。哦,实际上,我刚刚测试过(去掉所有的&lt;-:=),在我的电脑上roland3 = 2L - sequence(rle(as.integer(df$subj))$lengths) %% 2Lroland2
  • @Frank 随意编辑基准。然后我就不必运行它们了。
猜你喜欢
  • 2019-12-11
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2018-05-16
  • 1970-01-01
  • 2017-10-13
相关资源
最近更新 更多