【问题标题】:R: better data structures and algorithms for a complex problemR:针对复杂问题的更好的数据结构和算法
【发布时间】:2021-04-10 20:02:08
【问题描述】:

抱歉,问题太长了。我正在寻找针对复杂问题的更好数据结构和算法的建议。我正在分析数据以了解为什么某些白兰地品种具有完全不同的特征。存在导致差异的物质组(物质G1到物质G12)。根据白兰地中物质的数量和种类,饮料可以具有不同的颜色、透明度、味道、香气等。

表1包含白兰地和物质组的数量:

Variety substanceG      Amount
BrandyA substanceG1     5.1
BrandyA substanceG2     1.2
BrandyA substanceG3     2.3
BrandyB substanceG1     1.1
BrandyB substanceG2     2.5
BrandyB substanceG7     3.0
BrandyB substanceG11    3.5
...

物质组的成分见表2。所有数字均以百分比表示。 物质组的组成见表2。所有数字均以百分比表示。

substanceG  A       B   C   D   E       F
substanceG1 0.8     1.1 51  0   47.1    0   
substanceG2 23.4    0   4   12  58.8    1.8
substanceG3 47.9    32  0   0   0       20.1
...

众所周知,每个成分都会对白兰地的特性做出一定的贡献(表 3)。

Trait       A   B   C   D   E   F
Color       3   0   2   1   5   5
Transpar    1   4   0   6   2   2
Taste       0   5   1   0   7   1
NuttyAroma  3   7   0   4   4   0
Dryness     7   0   2   6   0   2

为清楚起见,以上三个表格都进行了简化。

对于每种白兰地,将针对每种特性计算物质组的总贡献。以白兰地A为例。物质 G1 中有5.1*0.8% 量的组分 A。所以5.1*0.8%*c(3,1,0,3,7)是A对substanceG1的贡献。物质 G1 中有5.1*1.1% 量的 B 组分。 5.1*1.1%*c(0,4,5,7,0) 是 B 在物质 G1 中的贡献...然后将所有内容相加:5.1*0.8%*c(3,1,0,3,7)+5.1*1.1%*c(0,4,5,7,0)+...+5.1*0%*c(5,2,1,0,2) 并移动到物质 G2、3 等等。或者,BrandyA 中 A 的总量可以通过5.1*0.8%+1.2*23.4%+2.3*47.9%, B 5.1*1.1%+1.2*0%+2.3*32%... 使用总和乘以表 3 中的各个列。在乘法之后计算行总和。这些是 BrandyA 中所有物质组的总贡献分数。

任何一种方式都有效。我编写了一个控制台脚本,它依赖于查询/条件子集表和循环来进行数学运算。它运行,但速度慢且容易出错。表格中的拼写错误很容易导致故障。必须有更好的方法,更有效的方法。您将如何解决这个问题?

【问题讨论】:

  • 矩阵乘法...????
  • 不幸的是,这些表不是同质的——它们包含文本列。因此,如果删除了这些列,则可以选择矩阵运算。第二个障碍是文本列都有不同的名称。

标签: r algorithm


【解决方案1】:

我认为这可以通过两个连接、一个乘法并将它们相加来非常简洁地完成。这将有助于将第 2 表和第 3 表重塑为更长的格式,以便第 2 表的每一行对应一种物质组组合,而第 3 表的每一行对应一种特征组组合。这样,您可以逐步将它们连接到前面的表中,以便为数据中的每个 Variety-substanceG-Trait 获取一行。

library(tidyverse)
df1 %>%
  left_join(df2 %>% pivot_longer(-substanceG)) %>%
  left_join(df3 %>% pivot_longer(-Trait), by = "name") %>% 
  mutate(contribution = Amount * value.x/100 * value.y) %>%
  count(Variety, Trait, wt = contribution)

结果:

  # A tibble: 10 x 3
   Variety Trait          n
   <chr>   <chr>      <dbl>
 1 BrandyA Color      27.7 
 2 BrandyA Dryness    17.1 
 3 BrandyA NuttyAroma 22.8 
 4 BrandyA Taste      28.8 
 5 BrandyA Transpar   12.6 
 6 BrandyB Color      13.6 
 7 BrandyB Dryness     7.37
 8 BrandyB NuttyAroma 11.0 
 9 BrandyB Taste      14.7 
10 BrandyB Transpar    6.51

来源数据:

df1 <- tibble::tribble(
  ~Variety, ~substanceG, ~Amount,
  "BrandyA", "substanceG1", 5.1,
  "BrandyA", "substanceG2", 1.2,
  "BrandyA", "substanceG3", 2.3,
  "BrandyB", "substanceG1", 1.1,
  "BrandyB", "substanceG2", 2.5
  # "BrandyB", "substanceG7", 3.0,   # excluded b/c not in other tables
  # "BrandyB", "substanceG11", 3.5   # excluded b/c not in other tables
)


df2 <- tibble::tribble(
  ~substanceG, ~A, ~B, ~C, ~D, ~E, ~F,
  "substanceG1", 0.8, 1.1, 51, 0, 47.1, 0,
  "substanceG2", 23.4, 0, 4, 12, 58.8, 1.8,
  "substanceG3", 47.9, 32, 0, 0, 0, 20.1,
)

df3 <- tibble::tribble(
  ~Trait, ~A, ~B, ~C, ~D, ~E, ~F,
  "Color", 3, 0, 2, 1, 5, 5,
  "Transpar", 1, 4, 0, 6, 2, 2,
  "Taste", 0, 5, 1, 0, 7, 1,
  "NuttyAroma", 3, 7, 0, 4, 4, 0,
  "Dryness", 7, 0, 2, 6, 0, 2
)

【讨论】:

  • 嗨乔恩。逻辑是合理的。这比我的嵌套循环要好得多。我将在我更大的数据集上尝试这个并报告回来。感谢您的帮助!
猜你喜欢
  • 1970-01-01
  • 2011-06-25
  • 2021-08-12
  • 2011-02-17
  • 1970-01-01
  • 2015-12-14
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多