【问题标题】:Count changes to contents of a character vector [duplicate]计数对字符向量内容的更改[重复]
【发布时间】:2015-03-31 18:47:10
【问题描述】:

我有一个data_frame,其中一个字符变量x 随时间变化。我想计算它改变的次数,并用这个计数填充一个新的向量。

df <- data_frame(
  x = c("a", "a", "b", "b", "c", "b"),
  wanted = c(1, 1, 2, 2, 3, 4)
)
  x wanted
1 a      1
2 a      1
3 b      2
4 b      2
5 c      3
6 b      4

这与rle(df$x) 相似但不同,后者将返回

Run Length Encoding
  lengths: int [1:4] 2 2 1 1
  values : chr [1:4] "a" "b" "c" "b"

我可以尝试rep() 那个输出。我也试过这个,非常接近,但不是因为我无法立即弄清楚的原因:

 df %>% mutate( 
   try_1 = cumsum(ifelse(x == lead(x) | is.na(lead(x)), 1, 0)) 
   )
Source: local data frame [6 x 3]

  x wanted try_1
1 a      1     1
2 a      1     1
3 b      2     2
4 b      2     2
5 c      3     2
6 b      4     3

似乎应该有一个直接执行此操作的函数,我只是在我的经验中没有发现。

【问题讨论】:

    标签: r dplyr


    【解决方案1】:

    试试这个dplyr代码:

    df %>%
      mutate(try_1 = cumsum(ifelse(x != lag(x) | is.na(lag(x)), 1, 0)))
    
      x wanted try_1
    1 a      1     1
    2 a      1     1
    3 b      2     2
    4 b      2     2
    5 c      3     3
    6 b      4     4
    

    你的意思是:如果一个值与下一行的值相同,或者如果下一行的值为 NA,则增加计数。

    这表示:如果该行上的变量与前一行上的变量不同,或者前一行(例如,第 1 行)上没有变量,则增加计数。

    【讨论】:

    • 你是用data.frame()创建的,原来的帖子是用data_frame()创建的。看起来这适用于字符变量,而不是一个因素。
    • 是的,如果我使用您帖子中的 data.frame 但添加 df$x &lt;- as.character(df$x) 它对我有用。
    • 您可以缩短代码 mutate(df, try_1 = cumsum(x!=lag(x)|is.na(lag(x)))),因为 TRUE/FALSE 将通过 cumsum 强制转换为数值 1/0
    • default 中的选项lag 也可以使用mutate(df, try_1 = cumsum(x!=lag(x, default=1)))
    【解决方案2】:

    你可以试试

    library(data.table) #data.table_1.9.5
    setDT(df)[, wanted := rleid(x)][]
    #    x wanted
    #1: a      1
    #2: a      1
    #3: b      2
    #4: b      2
    #5: c      3
    #6: b      4
    

    或者base R 选项将是

    inverse.rle(within.list(rle(as.character(df$x)),
                              values<- seq_along(values)))
    #[1] 1 1 2 2 3 4
    

    数据

    df <- data.frame(x=c("a", "a", "b", "b", "c", "b"))
    

    【讨论】:

    • 啊。为了避免引入data.table,我实际上所做的是从this comment复制代码rleid=function(x){r=rle(x);rep(1:length(r$lengths),r$lengths)}
    • @gregmacfarlane 也可以,但是,rleid 是一个不错的包装函数
    • 是的,这是一个不错的功能。事实上,这很像我在与rle() 输出争吵时的想法。但就我的目的而言,在我的脚本中包含该函数比引入 data.table 并担心名称冲突要容易。
    • rleid() 也适用于超过 1 列(并且为了速度而用 C 语言编写)。 @gregmacfarlane,您担心什么名称冲突?
    • last(),主要是。我意识到我可以明确或之后加载dplyr。但对于我们的应用程序,不使用data.table 会更容易。
    猜你喜欢
    • 1970-01-01
    • 2019-07-26
    • 2022-11-13
    • 2021-02-28
    • 2017-06-13
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多