【问题标题】:General Question about Finding Combination Matches关于查找组合匹配的一般问题
【发布时间】:2020-08-04 13:12:05
【问题描述】:

我对 R 编码非常陌生(请原谅我在术语、礼仪等方面的任何错误)。我决定开始一个项目,以便获得更多经验。我是一名研究动物骨骼的考古学家,在我的领域中,我们有一个称为最小元素数 (MNE) 的定量单位。这个单元手动计算很痛苦,我正在尝试自动计算。 MNE 是可以表示碎片骨骼集合的最小完整骨骼数量。所以,我有代表骨骼某些部分的骨骼部分代码,并且我已经制定了以特定顺序查找组合的规则。某些组合等于 1 个 MNE,等等。

这是我拥有的数据框的示例:

EL_S    PT
1P_L    1
HU_L    107,107,107,108,108
FE_L    103,105,108,110,103,103,108,110,105,107,103

EL_S 列表示骨骼元素和侧面(因此FE_L 等于左股骨),PT 列是与该骨骼和侧面相关的零件代码的字符向量。例如,103 和 105 的组合等于 1 个 MNE。更具体地说,最好的方法是:

  1. 为 PT 组合分配某些值(但是,PT 1 等于整根骨头,是 1 个 MNE。所以,即使它不是组合,我也必须给它一个值。)

  2. 从字符向量中查找并提取这些组合(或单个值)

  3. 统计它们的出现

  4. 将该计数加载到新的“MNE”列

  5. 并按照指定的顺序完成所有这些操作

我当然意识到这是来自这个社区的疯狂的具体要求。我完全不指望有人会为我解决所有这些问题。但是,如果有人对这个过程中的任何步骤有任何关于使用特定功能等的建议,我将非常感激。我正在考虑使用 stringr 将代码字符串组合成 103105,然后计算这些匹配项。但我不太确定这是最有效的方法。再次,非常感谢这里的任何帮助!

编辑澄清:

在一个完美的世界里,这就是我希望创造的。

我从上面的例子开始:

EL_S    PT
1P_L    1
HU_L    107,107,107,108,108
FE_L    103,105,108,110,103,103,108,110,105,107,103

我想先找到并提取 PT 1。该部分代码等于 1 个 MNE。

EL_S    PT                                          MNE
1P_L                                                1
HU_L    107,107,107,108,108
FE_L    103,105,108,110,103,103,108,110,105,107,103

接下来我要查找并提取组合 103,105。这等于 1 个 MNE。在上表中,FE_L 有 103,105 个组合的两个实例,因此 MNE = 2。

EL_S    PT                            MNE
1P_L                                  1
HU_L    107,107,107,108,108
FE_L    108,110,103,103,108,110,107   2

这种情况会一直持续下去,直到不再有零件代码。在找到特定组合(或单个 PT 值)时添加到 MNE 列。我希望这是有道理的。如果这里有任何不清楚的地方,我们深表歉意。

【问题讨论】:

  • 嗨 Thanatocoenose(相关名称,必须谷歌搜索)。我最初的想法是使用tidyr::separate_rowsPT 列拆分为长格式。在这种情况下这有意义吗?零件代码的顺序重要吗?
  • 感谢您的名字恭维!零件代码的顺序通常在数据帧内是非结构化的。但它们被发现、提取和统计的顺序确实很重要。我最初使用的是长格式,但我对其进行了转换,因为我认为它可能更容易在视觉上表示。我正在考虑使用 stringr 并将这些字符向量分配到它们相应的 EL_S 上。但我对 stringr 的想法越多,我就越觉得我可能会浪费我的时间……而且我应该寻求帮助/建议。哈哈哈。
  • 我将编辑我之前的帖子,以便更清楚地说明我在这里要做什么。

标签: r pattern-matching matching string-matching


【解决方案1】:

假设df 看起来像这样:

df <- read.table(text = "EL_S    PT
1P_L    1
HU_L    107,107,107,108,108
FE_L    103,105,108,110,103,103,108,110,105,107,103", header = TRUE)


  EL_S                                          PT
1 1P_L                                           1
2 HU_L                         107,107,107,108,108
3 FE_L 103,105,108,110,103,103,108,110,105,107,103

我们可以把它变成宽格式,并添加你想要计数的列,该列最初用零填充:

library(tidyverse)

df_wide <- df %>% 
  separate_rows("PT") %>% 
  count(EL_S, PT) %>% 
  spread(PT, n, fill = 0) %>% 
  mutate(MNE = 0)


# A tibble: 3 x 8
  EL_S    `1` `103` `105` `107` `108` `110`   MNE
  <fct> <dbl> <dbl> <dbl> <dbl> <dbl> <dbl> <dbl>
1 1P_L      1     0     0     0     0     0     0
2 FE_L      0     4     2     1     2     2     0
3 HU_L      0     0     0     3     2     0     0

我认为我们需要迭代地进行(因为我们做事的顺序很重要)。
您示例中的第一步是零件代码1。我们选择正确的计数列,应用最小值,将其添加到计数列,然后从我们考虑的观察中减去。

part_codes <- c("1")
num_mne <- apply(df_wide[part_codes], 1, FUN=min)
df_wide$MNE <- df_wide$MNE + num_mne
df_wide[part_codes] <- df_wide[part_codes] - num_mne


# A tibble: 3 x 8
  EL_S    `1` `103` `105` `107` `108` `110`   MNE
  <fct> <dbl> <dbl> <dbl> <dbl> <dbl> <dbl> <dbl>
1 1P_L      0     0     0     0     0     0     1
2 FE_L      0     4     2     1     2     2     0
3 HU_L      0     0     0     3     2     0     0

那么,我们可以对103,105做同样的事情:

part_codes <- c("103", "105")
num_mne <- apply(df_wide[part_codes], 1, FUN=min)
df_wide$MNE <- df_wide$MNE + num_mne
df_wide[part_codes] <- df_wide[part_codes] - num_mne


# A tibble: 3 x 8
  EL_S    `1` `103` `105` `107` `108` `110`   MNE
  <fct> <dbl> <dbl> <dbl> <dbl> <dbl> <dbl> <dbl>
1 1P_L      0     0     0     0     0     0     1
2 FE_L      0     2     0     1     2     2     2
3 HU_L      0     0     0     3     2     0     0

由于除了 part_codes 变量之外的代码是相同的,我认为您可以将其包装在一个函数中并循环(或应用)您要处理的部分代码组合。

这是你想要的吗?

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2018-01-21
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多