Python 或 R 函数根据所有测试变量的相似度百分比对多元化学数据进行分组

问题描述 投票:0回答:1

我在编程方面是个新手,但使用 GIS 软件在空间上绘制测试了多个变量(n=16 个元素)的样本(n=2000)。我正在尝试使用 Python 或 R(或实际上的任何语言)根据所有测试元素的相对相似性 (%) 来统计划分化学相关的基团。

使用值的 + 或 - 10% 的示例:

          Al    Na    K     Si
Sample1   1     2     3     4
Sample2   1.5   2.5   3.5   4.5 
Sample3   1.05  2.1   3.1   1
Sample4   0.95  1.9   3.1   3.8

想要的结果:

  • 样本 1 将与样本 4 位于一组(所有四个值彼此相差 10% 以内)。
  • Sample2 将独立存在。
  • Sample3 也将是独立的,因为即使前三个元素在 Sample1 的 10% 范围内,但最后一个元素 (Si) 不在其中,因此不会分组。

我查看了一些线程,但似乎没有一个线程将所有变量关联在一起,并且只会根据一个线程进行分组。

python r
1个回答
0
投票

由于您想要按值进行比较,因此 DBSCAN 或 K 均值等标准聚类方法将不起作用,因为它们使用点之间的聚合距离。

为此,您可以通过将每个项目与所有其他项目进行比较来找到每个值的最大差异(以百分比形式)来进行暴力破解。函数

max_pct_difference
计算最大百分比差异。这些 X 到 Y 的差异创建了您感兴趣的“距离”矩阵的下半部分。

通过预先计算距离矩阵,您可以在 DBSCAN 等聚类算法中使用它。这会将距离小于参数 epsilon 的相似项目分组在一起。但您必须注意,并非组中的所有项目的距离都小于 10%。这是因为您可以得到这样的样本:A 在 B 的 10% 范围内,B 在 C 的 10% 范围内,但 A 和 C 不在 10% 范围内:

A   1.0  1.0  1.0  2.1
B   1.0  1.0  1.0  2.3
C   1.0  1.0  1.0  2.4

这里有一些代码可以帮助您入门:

import pandas as pd
from itertools import combinations_with_replacement

df = pd.DataFrame(
 {'Al': {'Sample1': 1.0, 'Sample2': 1.5, 'Sample3': 1.05, 'Sample4': 0.95},
  'Na': {'Sample1': 2.0, 'Sample2': 2.5, 'Sample3': 2.1, 'Sample4': 1.9},
  'K': {'Sample1': 3.0, 'Sample2': 3.5, 'Sample3': 3.1, 'Sample4': 3.1},
  'Si': {'Sample1': 4.0, 'Sample2': 4.5, 'Sample3': 1.0, 'Sample4': 3.8}}
)

def max_pct_difference(s1: tuple, s2: tuple):
    max_diff = 0.0
    for x, y in zip(s1[1:], s2[1:]):
        # handle division by zero
        if x == 0 and y == 0:
            continue
        diff = abs(x - y) / max(x, y)
        max_diff = max(diff, max_diff)
    return diff


pairs = []
for s1, s2 in combinations_with_replacement(df.itertuples(), 2):
    max_diff = max_difference(s1, s2)
    # append s1, s2 and then s2, s1 to make the matrix symmetric
    pairs.append((s1.Index, s2.Index, max_diff))
    if s1.Index != s2.Index:
        pairs.append((s2.Index, s1.Index, max_diff))


# this creates the distance matrix
dist_df = pd.DataFrame(pairs, columns=['X', 'Y', 'd']).set_index(['X','Y']).unstack(level=1)

创建距离矩阵后,您可以使用 DBSCAN 查找距离阈值 epsilon 内的簇/组。对于参数,如果您想保留至少有 2 个点接近的所有组,则需要设置

eps=0.1
并将每个簇的最小点数设置为 2。对于度量,我们将使用
"precomputed"
,因为我们已经以自定义方式预先计算了距离。

from sklearn.cluster import DBSCAN

dbs = DBSCAN(eps=0.1, min_samples=2, metric='precomputed')

# get the group label for each item in the distance data frame
groups = dbs.fit_predict(dist_df)

# assign the group label to the corresponding sample
df['Group'] = groups

print(df)
# prints:
#            Al   Na    K   Si  Group
# Sample1  1.00  2.0  3.0  4.0      0
# Sample2  1.50  2.5  3.5  4.5     -1
# Sample3  1.05  2.1  3.1  1.0     -1
# Sample4  0.95  1.9  3.1  3.8      0

此示例中只有一个组,即组

0
,它被分配给样本 1 和 4。标有组 -1 的行没有组。

最新问题
© www.soinside.com 2019 - 2024. All rights reserved.