如何从python中的字符索引中找到行号?

问题描述

我有一个遗传数据集,其中行的索引是基因的名称。我还希望找到任何给定基因的行号,以便在它们经过机器学习模型预测后可以逐个查看这些基因,以便从头到尾地解释该基因的预测。目前,我如何为整形图编写代码需要一个行号来提取特定基因。

我的数据如下:

Index   Feature1  Feature2   ... FeatureN
Gene1     1           0.2          10
Gene2     1           0.1          7
Gene3     0           0.3          10

例如,如果我想退出并查看Gene3的模型预测,则可以这样做:

import shap
shap.initjs()

xgbr = xgboost.XGBRegressor()

def shap_plot(j):
    explainerModel = shap.TreeExplainer(xgbr)
    shap_values_Model = explainerModel.shap_values(X_train)
    p = shap.force_plot(explainerModel.expected_value,shap_values_Model[j],X_train.iloc[[j]],feature_names=df.columns)
    return(p)

shap_plot(3)

shap_plot(3)对我来说是个问题,因为我实际上并不知道我想要的基因是否在改组的训练或测试数据的第3行中。

有没有办法从已知的基因索引中提取行号?还是可能重新编码我的图形,使其接受我的字符串索引我有生物学背景,因此任何指导都将受到赞赏。

解决方法

尝试以下方法。 df是您的数据框,结果将为您提供给定基因的行号(第一行将为1,依此类推)

list(df.index).index('Gene3')+1

#result

3
,

有很多方法可以获取与索引值或列值关联的行号。

例如,如果您的基因实际上位于名为"Index"的列中,则可以执行以下操作:

x_train[x_train["Index"] == "gene3"].index + 1

,如果没有,您总是可以通过在数据帧上调用reset_index()来实现。

另一种选择是,例如,在数据框中添加一个从1到n的新列

mapping = x_train.assign(index_number=range(x_train.shape[0]))["index_number"]

现在mapping应该看起来像这样:

Index   index_mapping 
Gene1     0           
Gene2     1           
Gene3     2           

并调用mapping["Gene2"]应该返回1

除此之外,我注意到您正在使用力图。我建议您阅读this article,了解为何shap用决策图代替了它们。

此外,每次调用函数时都在重新构建树解释器。这效率很低,为什么不先构建一次,然后多次查询:

class ShapPlotter:
    def __init__(self,model,x_train):
        self.explainer_model = shap.TreeExplainer(model)
        self.shap_values_Model = self.explainer_model.shap_values(x_train)
        self.gene_index_mapping = x_train.assign(index_value=range(x_train.shape[0]))["index_value"]

    def plot(gene):
        idx = self._get_index(gene)
        shap_plot = shap.force_plot(...) # replace j with idx here
        return shap_plot

    def _get_index(gene: str) -> int:
        # your choice of method here. e.g. https://stackoverflow.com/a/64279019/1011724
        # in this case,I built a mapping series in the __init__ fn so you can get the index number by just indexing directly with the gene string: 
        return self.gene_index_mapping.loc[gene]
,
list(df[df.Index=='Gene3'].index)