【问题标题】:how to replace values in matrix if they have the same beginning?如果它们具有相同的开头,如何替换矩阵中的值?
【发布时间】:2018-10-30 06:30:26
【问题描述】:

我有一个很大的杂货矩阵。 有些值是相同的,但名称不同。 例如:

Ketchup  Ketchupwithgarlic  Ketchupspicy Chips Chipsorganic
0               1               0         0      1
1               0               0         0      0
0               0               0         1      0
1               0               0         0      0

如果一个名称以完全相同的名称开头,我想做的是将这两个向量组合成一个向量,因此输出如下所示:

Ketchup Chips
1        1
1        0
0        1
1        0

我该怎么办?

【问题讨论】:

  • 这是data.frame还是矩阵?请使用dput 提供一个稍大的示例。也许有两个或三个列类别。
  • 如果有三列呢?你想把这三个结合起来吗?结合你的意思是sum 对吗?
  • 它是一个推荐系统的矩阵。我想减小矩阵的大小,因为某些产品可以轻松更换。我希望它们成为一种产品,而不是三种不同的产品

标签: r matrix


【解决方案1】:

我相信这可以满足您的需求。至少对于您提供的数据集是这样。而且它不依赖于硬编码的列名。

使用@MKR 答案中的代码读取的数据:

nms <- names(df)
inx <- which(sapply(seq_along(nms), function(i) any(grepl(paste0("^", nms[i]), nms[-i]))))
result <- sapply(inx, function(i) rowSums(df[, grep(nms[i], nms)]))
colnames(result) <- nms[inx]
result
#     Ketchup Chips
#[1,]       1     1
#[2,]       1     0
#[3,]       0     1
#[4,]       1     0

【讨论】:

    【解决方案2】:

    将矩阵转换为data.frame 后,可以访问使用dplyr::coalesce 的选项。此外,值为0 的单元格应更改为NA 以应用coalesce

    library(dplyr)
    # First change matrix to data.frame. The same data is created in data.frame 
    # so this step can be skipped
    df <- as.data.frame(df)
    
    # Replace 0 with NA
    df[df==0] <- NA
    

    选项#1:如果列名较少且已知,则一次接近

    bind_cols(Chips = coalesce(!!!select(df, starts_with("Chips"))), 
              Ketchup = coalesce(!!!select(df, starts_with("Ketchup"))) )
    # # A tibble: 4 x 2
    #   Chips Ketchup
    #   <int>   <int>
    # 1     1       1
    # 2    NA       1
    # 3     1      NA
    # 4    NA       1
    

    选项#2:通用方法可以写成:

    overlapName <- names(df)[mapply(function(x)sum(str_detect(names(df),x)), names(df)) >1]
    library(stringr)
    
    mapply(function(x)coalesce(!!!select(df, starts_with(x))), overlapName)
    #      Ketchup Chips
    # [1,]       1     1
    # [2,]       1    NA
    # [3,]      NA     1
    # [4,]       1    NA
    

    数据:

    df <- read.table(text = 
    "Ketchup  Ketchupwithgarlic  Ketchupspicy Chips Chipsorganic
    0               1               0         0      1
    1               0               0         0      0
    0               0               0         1      0
    1               0               0         0      0",
    header = TRUE, stringsAsFactors = FALSE)
    

    【讨论】:

    • 谢谢!但是,如果我想对矩阵中的所有产品都这样做怎么办。例如:苹果和苹果绿、冰淇淋和冰淇淋巧克力
    • @nurma_a 我提供了一个选项,以便可以为一组完成。现在我们需要扩大它以覆盖所有列。
    • @RonakShah 我同意你的看法。我们必须找到一种方法来找到在其他列中重复的常见唯一名称。
    • @RonakShah 我已经更新了我的答案,以包含一种检测重叠列并将其用作输入的通用方法。
    【解决方案3】:

    这是另一种基本的 R 替代方案。我认为 Rui Barrades 的答案可能更好,但了解多种方法可能会有所帮助。

    # save column names
    cnms <- colnames(myMat)
    # build a matrix that groups on column names using col and grepl
    grps <- col(diag(length(cnms))) * sapply(cnms[order(cnms)], grepl, x=cnms)
    # run through the groups and perform rowSums to collapse groups into one column
    sapply(split(seq_len(ncol(myMat)), 
                 colnames(grps)[apply(grps, 1, FUN=function(x) min(x[x != 0]))]),
           function(y) rowSums(myMat[, y]))
    

    返回

         Chips Ketchup
    [1,]     1       1
    [2,]     0       1
    [3,]     1       0
    [4,]     0       1
    

    数据

    myMat <-
    structure(c(0L, 1L, 0L, 1L, 1L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 
    0L, 1L, 0L, 1L, 0L, 0L, 0L), .Dim = 4:5, .Dimnames = list(NULL, 
        c("Ketchup", "Ketchupwithgarlic", "Ketchupspicy", "Chips", 
        "Chipsorganic")))
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2019-10-19
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2018-02-22
      • 1970-01-01
      • 1970-01-01
      • 2021-09-28
      相关资源
      最近更新 更多