【问题标题】:How to extract rows with similar names into a submatrix?如何将具有相似名称的行提取到子矩阵中?
【发布时间】:2023-04-05 06:39:01
【问题描述】:

我正在构建一个不对称的值矩阵,其中行是系数名称,列是每个系数的值:

 #                          Set up Row and Column Names.


rows = c("Intercept", "actsBreaks0", "actsBreaks1","actsBreaks2","actsBreaks3","actsBreaks4","actsBreaks5","actsBreaks6",
            "actsBreaks7","actsBreaks8","actsBreaks9","tBreaks0","tBreaks1","tBreaks2","tBreaks3", "unitBreaks0", "unitBreaks1",
            "unitBreaks2","unitBreaks3", "covgBreaks0","covgBreaks1","covgBreaks2","covgBreaks3","covgBreaks4","covgBreaks5",
            "covgBreaks6","yearBreaks2016","yearBreaks2015","yearBreaks2014","yearBreaks2013","yearBreaks2011",
            "yearBreaks2010","yearBreaks2009","yearBreaks2008","yearBreaks2007","yearBreaks2006","yearBreaks2005",
            "yearBreaks2004","yearBreaks2003","yearBreaks2002","yearBreaks2001","yearBreaks2000","yearBreaks1999",
            "yearBreaks1998","plugBump0","plugBump1","plugBump2","plugBump3")
cols = c("Value")

#                           Build Matrix

matrix1 <- matrix(c(1:48), nrow = 48, ncol = 1, byrow = TRUE, dimnames = list(rows,cols))

输出:

> matrix1
               Value
Intercept          1
actsBreaks0        2
actsBreaks1        3
actsBreaks2        4
actsBreaks3        5
actsBreaks4        6
actsBreaks5        7
actsBreaks6        8
actsBreaks7        9
actsBreaks8       10
actsBreaks9       11
tBreaks0          12
tBreaks1          13
tBreaks2          14
tBreaks3          15
unitBreaks0       16
unitBreaks1       17
unitBreaks2       18
unitBreaks3       19
covgBreaks0       20
covgBreaks1       21
covgBreaks2       22
covgBreaks3       23
covgBreaks4       24
covgBreaks5       25
covgBreaks6       26
yearBreaks2016    27
yearBreaks2015    28
yearBreaks2014    29
yearBreaks2013    30
yearBreaks2011    31
yearBreaks2010    32
yearBreaks2009    33
yearBreaks2008    34
yearBreaks2007    35
yearBreaks2006    36
yearBreaks2005    37
yearBreaks2004    38
yearBreaks2003    39
yearBreaks2002    40
yearBreaks2001    41
yearBreaks2000    42
yearBreaks1999    43
yearBreaks1998    44
plugBump0         45
plugBump1         46
plugBump2         47
plugBump3         48

我希望将某些共享行名的行(即所有带有“unitBreaks'x'”的行)提取到子矩阵中。

我试过了

est_actsBreaks <- est_coef_mtrx[c("actsBreaks0","actsBreaks1","actsBreaks2","actsBreaks3",
                                  "actsBreaks4","actsBreaks5","actsBreaks6","actsBreaks7",
                                  "actsBreaks8","actsBreaks9"),c("Value")]

但它返回一个向量,我需要一个矩阵。我见过其他关于类似程序的问题,但它们的列和行都有相同的名称和/或值。有没有办法做我想到的操作,比如grep()

【问题讨论】:

    标签: r matrix


    【解决方案1】:

    欢迎来到 StackOverflow。

    像往常一样在 R 中,可能有很多方法可以满足您的要求。


    编辑:我意识到我的解决方案有点过头了,对此感到抱歉。

    要仅提取包含模式“unitBreaks”后跟多个数字的行,并且仍然保持矩阵结构,您可以运行以下代码。简而言之,grep 将寻找您需要的模式,而参数drop = FALSE 将确保您得到一个矩阵而不是向量。

    uniBreakLines <- grep("unitBreaks[0-9]*", rows)
    matrix1[uniBreakLines, , drop = FALSE]
    

    以下是我的答案的第一个版本。

    首先,我创建一个描述行组的向量。为此,我删除了行名末尾的数字。

    grp <- gsub("[0-9]+$", "", rows)
    

    然后,我将数据矩阵转换为数据帧(我这样做的原因稍后会解释)。

    dat1 <- data.frame(matrix1)
    

    最后,我在数据框上使用“拆分”,以及前面定义的组。对数据框使用 split 将保持结构:结果将是数据框列表,即使只有一列。

    dat1.split <- split(dat1, grp)
    

    结果是一个数据框列表。

    lapply(dat1.split, head)
    
    $actsBreaks
                Value
    actsBreaks0     2
    actsBreaks1     3
    actsBreaks2     4
    actsBreaks3     5
    actsBreaks4     6
    actsBreaks5     7
    
    $covgBreaks
                Value
    covgBreaks0    20
    covgBreaks1    21
    covgBreaks2    22
    covgBreaks3    23
    covgBreaks4    24
    covgBreaks5    25
    
    $Intercept
              Value
    Intercept     1
    
    $plugBump
              Value
    plugBump0    45
    plugBump1    46
    plugBump2    47
    plugBump3    48
    
    $tBreaks
             Value
    tBreaks0    12
    tBreaks1    13
    tBreaks2    14
    tBreaks3    15
    
    $unitBreaks
                Value
    unitBreaks0    16
    unitBreaks1    17
    unitBreaks2    18
    unitBreaks3    19
    
    $yearBreaks
                   Value
    yearBreaks2016    27
    yearBreaks2015    28
    yearBreaks2014    29
    yearBreaks2013    30
    yearBreaks2011    31
    yearBreaks2010    32
    

    之后,如果您仍然需要矩阵,可以在“lapply”中使用函数as.matrix 进行转换:

    matrix1.split <- lapply(dat1.split, as.matrix)
    

    您可能需要考虑将“tibble”中的数据与“grouping”列合并。然后,您将能够将这些组与 group_by 函数或 dplyr 包(或 tidyverse 中的其他包)中的其他函数一起使用。

    例如:

    library(dplyr)
    tib1 <- tibble(rows, simpler_rows, value = 1:48)
    

    以及如何使用分组变量的示例:

    tib1 %>%
      group_by(simpler_rows) %>%
      summarize(sum(value))
    

    编辑之二:如果我不知道模式怎么办?

    我用你的例子来回答这个问题(没人问,但仍然很有趣!):“如果我不知道模式怎么办?”

    在这种情况下,我会使用行名之间的距离。这个距离应该是这样的:

    ...并且将是以下代码行的输出

    library(stringdist)
    library(pheatmap)
    
    strdist <- stringdistmatrix(rows)
    pheatmap(strdist, border_color = "white", cluster_rows = F, cluster_cols = FALSE, cellwidth = 10, cellheight = 10, labels_row = rows, fontsize_row = 7)
    

    之后,我只需要得到簇的数量,这可以用一个剪影图(类似于这个)来完成,它告诉我有 8 个词簇,这似乎是正确的:

    然后可以使用用于创建轮廓图的函数提取集群(我使用了hclustcutree)。

    【讨论】:

    • 我应该能够正确地将这些数据帧转换回矩阵吗?
    • 当然,我要为此添加一行。
    • 对不起,我读你的问题太快了,我用两行代码更新了我的答案,准确地回答了你的问题。如果我可能会问:为什么在操作结束时绝对需要一个矩阵?
    • 这有很好的功能。谢谢!
    • 我正在使用具有 7 个变量“家族”的 glm 的系数并将它们应用于数据集以测试模型的功效,我认为最简单的方法是将每个“x”矩阵的每个 beta 矩阵。
    【解决方案2】:

    这里有一个使用dplyrstringr 的解决方案来提取包含特定字符串的行名。 最后改回矩阵:

    library(dplyr)
    library(stringr)
    df1 <- df %>% 
        filter(!str_detect(rownames(df), "unitBreaks")) 
    
    df1 <- as.matrix(df1)
    
                   Value
    Intercept          1
    actsBreaks0        2
    actsBreaks1        3
    actsBreaks2        4
    actsBreaks3        5
    actsBreaks4        6
    actsBreaks5        7
    actsBreaks6        8
    actsBreaks7        9
    actsBreaks8       10
    actsBreaks9       11
    tBreaks0          12
    tBreaks1          13
    tBreaks2          14
    tBreaks3          15
    covgBreaks0       20
    covgBreaks1       21
    covgBreaks2       22
    covgBreaks3       23
    covgBreaks4       24
    covgBreaks5       25
    covgBreaks6       26
    yearBreaks2016    27
    yearBreaks2015    28
    yearBreaks2014    29
    yearBreaks2013    30
    yearBreaks2011    31
    yearBreaks2010    32
    yearBreaks2009    33
    yearBreaks2008    34
    yearBreaks2007    35
    yearBreaks2006    36
    yearBreaks2005    37
    yearBreaks2004    38
    yearBreaks2003    39
    yearBreaks2002    40
    yearBreaks2001    41
    yearBreaks2000    42
    yearBreaks1999    43
    yearBreaks1998    44
    plugBump0         45
    plugBump1         46
    plugBump2         47
    plugBump3         48
    

    【讨论】:

    • 您的解决方案中是否缺少我的步骤?当我尝试执行 df1 &lt;- df %&gt;% filter(!str_detect(rownames(df), "unitBreaks")) 时出现错误:no applicable method for 'filter' applied to an object of class "function"
    • 你有没有加载包library(dplyr) library(stringr)
    • 我做到了:library(dplyr) Attaching package: ‘dplyr’ The following object is masked from ‘package:MASS’: select The following object is masked from ‘package:car’: recode The following objects are masked from ‘package:stats’: filter, lag The following objects are masked from ‘package:base’: intersect, setdiff, setequal, union &gt; library(stringr) &gt; df1 &lt;- df %&gt;% + filter(!str_detect(rownames(df), "unitBreaks")) Error in UseMethod("filter") : no applicable method for 'filter' applied to an object of class "function"
    • 看起来加载的库很好。
    猜你喜欢
    • 2020-06-18
    • 1970-01-01
    • 2022-06-13
    • 1970-01-01
    • 2012-12-27
    • 2020-12-02
    • 1970-01-01
    • 1970-01-01
    • 2017-09-20
    相关资源
    最近更新 更多