【问题标题】:Split a column, get the mean of the split columns, and update the result拆分一列,获取拆分列的平均值,并更新结果
【发布时间】:2019-01-25 21:59:49
【问题描述】:

我目前正在尝试将包含值范围(作为字符)的列分隔为两个数字列,以计算它们的平均值(如果行具有范围)。然后,我想用更新的结果替换旧列。实际上,有多个专栏要做。我试图找到一种方法,但这对我来说似乎具有挑战性。

下面是我尝试过的代码..它不起作用..

test.val <- data.table(id = c(1, 2, 3), 
                       colA = c("100-150", "200", "300"), 
                       colB = c("15", "20-30", "10"))
test.A <- test.val[, lapply(.SD, function(x){strsplit(x, split = "-")}), .SDcols = c("colA", "colB")]
test.B[, lapply(.SD, mean), .SDcols = c("colA", "colB")]

最后,我想要以下内容:

   id colA colB
1:  1  125   15
2:  2  200   25
3:  3  300   10

谁能帮帮我? 非常感谢。

【问题讨论】:

    标签: r data.table strsplit


    【解决方案1】:

    另一个使用data.table的选项

    library(data.table)
    cols <- c("colA", "colB")
    for(j in cols) {
      tmp <- vapply(strsplit(test.val[[j]], "-"), 
                    FUN = function(i) mean(as.numeric(i)), 
                    FUN.VALUE = numeric(1))
      set(test.val, j = j, value = tmp)
    }
    test.val
    #   id colA colB
    #1:  1  125   15
    #2:  2  200   25
    #3:  3  300   10
    

    给定一个向量

    x <- c("100-150", "200", "300")
    

    strsplit 的结果是一个字符向量列表

    strsplit(x, "-")
    #[[1]]
    #[1] "100" "150"
    
    #[[2]]
    #[1] "200"
    
    #[[3]]
    #[1] "300"
    

    我们将其包装到vapply 中,并在将每个向量转换为数值后计算每个元素的平均值。

    vapply(strsplit(x, "-"), function(x) mean(as.numeric(x)), numeric(1))
    # [1] 125 200 300
    

    我们使用此结果替换 cols 中指定的每一列,使用 data.tableset 函数。

    【讨论】:

    • 我对 data.table 比其他数据结构更熟悉,这对我来说是一个非常好的答案。谢谢!
    • 另一种可能:test.val[, lapply(.SD, function(x) mean(as.numeric(strsplit(x,"-")[[1]]))), by=seq_len(test.val[,.N]), .SDcols=colA:colB]
    【解决方案2】:

    这是tidyverse 的一种可能性:

    test.val %>%
     gather(var, val, -id) %>%
     separate(val, c("val1", "val2"), sep = "-", convert = TRUE) %>%
     mutate(res = rowMeans(.[, 3:4], na.rm = TRUE)) %>%
     select(-val1, -val2) %>%
     spread(var, res)
    
      id colA colB
    1  1  125   15
    2  2  200   25
    3  3  300   10
    

    第一步,它将数据从宽格式转换为长格式。然后,它将值分成两列。最后,它计算行均值并将数据转换回原始格式。

    考虑到您想要分隔的每列可能有两个以上的值:

    test.val %>%
     gather(var, val, -id) %>%
     mutate(val = strsplit(val, "-")) %>%
     unnest(val) %>%
     group_by(id, var) %>%
     mutate(res = mean(as.numeric(val))) %>%
     distinct(res) %>%
     spread(var, res)
    

    【讨论】:

    • 谢谢@tmfmnk。
    • 这正是我想要的。
    猜你喜欢
    • 2015-01-24
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多