【问题标题】:R- Create a variable that is conditional upon row valuesR-创建一个以行值为条件的变量
【发布时间】:2014-11-03 10:21:08
【问题描述】:

我有一个如下所示的数据框测试:

ID  Month1  Month2  Month3  Month4  Month5  Month6  Month7  Month8
    A   0       1      1       1       1        0       0        0
    B   0       1      1       1       0        0      NA        NA
    C   0       0      0       0       NA      NA      NA        NA
    D   0       1      1       1       1        1       1        1
    E   0       1      1       0       0        0       1        1
    F   0       0      0       1       1        1       1        1
    G   0       0      1       1       0        0       0        0
    H   0       0      0       0       0        0       0        0

我想在数据框中创建一个条件变量“Result”,用于计算 1 连续重复的次数。但是,我只想计算后跟 0 的第一组 1,这意味着在创建“Result”变量时需要牢记三个条件。 条件如下:

条件一: 计算以 0 结尾的第一组 1。

条件 2: 如果1的集合不以0结尾或以NA结尾,则Result=NA

条件 3 如果有两组以 0 结尾的 1,则忽略第二组。

ID  Month1  Month2  Month3  Month4  Month5  Month6  Month7  Month8  Result 
    A   0       1      1       1       1        0       0        0       4
    B   0       1      1       1       0        0      NA        NA      3
    C   0       0      0       0       NA      NA      NA        NA     0
    D   0       1      1       1       1        1       1        1      NA
    E   0       1      1       0       0        0       1        1      2
    F   0       0      0       1       1        1       1        1      NA
    G   0       0      1       1       0        0       0        0      2
    H   0       0      0       0       0        0       0        0      0

到目前为止我已经尝试过:

test$Result=apply(test[,c(2:9)],1,function(x) length(x[x==1&!(is.na(x))])) 

这会计算行中 1 的总数,而不仅仅是第一组。

任何和所有的帮助将不胜感激。

【问题讨论】:

    标签: r conditional


    【解决方案1】:

    我认为在这里使用rle() 计算“值的运行长度”会有所帮助。以下是我假设您的数据存储在 R

    中的方式
    dd <- structure(list(ID = structure(1:8, .Label = c("A", "B", "C", 
        "D", "E", "F", "G", "H"), class = "factor"), Month1 = c(0L, 0L, 
        0L, 0L, 0L, 0L, 0L, 0L), Month2 = c(1L, 1L, 0L, 1L, 1L, 0L, 0L, 
        0L), Month3 = c(1L, 1L, 0L, 1L, 1L, 0L, 1L, 0L), Month4 = c(1L, 
        1L, 0L, 1L, 0L, 1L, 1L, 0L), Month5 = c(1L, 0L, NA, 1L, 0L, 1L, 
        0L, 0L), Month6 = c(0L, 0L, NA, 1L, 0L, 1L, 0L, 0L), Month7 = c(0L, 
        NA, NA, 1L, 1L, 1L, 0L, 0L), Month8 = c(0L, NA, NA, 1L, 1L, 1L, 
        0L, 0L)), .Names = c("ID", "Month1", "Month2", "Month3", "Month4", 
        "Month5", "Month6", "Month7", "Month8"), class = "data.frame", 
        row.names = c(NA, -8L))
    

    然后我会运行类似的代码

    dd$Result <- apply(dd[, -1], 1, function(x) {
        rr<-rle(x)
        f1<-which(rr$values==1)[1]
        if ( is.na(f1) ) {
            0
        } else if (!is.na(rr$values[f1+1]) && rr$values[f1+1]==0) {
            rr$lengths[f1]
        } else {
            NA
        }
    })
    

    给了

      ID Month1 Month2 Month3 Month4 Month5 Month6 Month7 Month8 Result
    1  A      0      1      1      1      1      0      0      0      4
    2  B      0      1      1      1      0      0     NA     NA      3
    3  C      0      0      0      0     NA     NA     NA     NA      0
    4  D      0      1      1      1      1      1      1      1     NA
    5  E      0      1      1      0      0      0      1      1      2
    6  F      0      0      0      1      1      1      1      1     NA
    7  G      0      0      1      1      0      0      0      0      2
    8  H      0      0      0      0      0      0      0      0      0
    

    如你所愿。

    您确实有一些边缘情况使此代码有些棘手。首先我们必须看到有任何 1;如果没有,我们返回 0。如果有一个,我们要确保它后面跟着一个 0,否则返回 NA。我们使用apply() 对每一行执行此逻辑,省略 ID 列。从您的描述中并不完全清楚NA 值如果出现在行尾之前(如开头)会发生什么情况,所以我假设这是您不必担心的情况。

    【讨论】:

    • 没错,我不必查看 NA 出现在 1 之前的情况。谢谢!
    【解决方案2】:

    这应该可以工作,尽管可能有一个更整洁的解决方案:

    FindResult = function(x)
    {
        RLE = rle(x)
        i = which(RLE$values == 1)[1]
        if(is.na(i))
            return(0)
    
        if (length(RLE$values) > i & RLE$values[i + 1] == 0)
            return(RLE$lengths[i])
        else
            return(NA)
    }
    
    Result = apply(df[,-1], 1, FindResult)
    > Result
    [1]  4  3  0 NA  2 NA  2  0
    

    【讨论】:

    • 呵呵。令人惊讶的是,鉴于我在努力寻求解决方案时几次改变主意,我们的代码最终如此相似。
    猜你喜欢
    • 2016-10-21
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2015-06-19
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多