Python复杂分组方式

2024-06-02 10:32:34 发布

您现在位置:Python中文网/ 问答频道 /正文

我有一个熊猫数据框(df),有3列: “药物”、“影响”、“杂志” 每一行都是一篇科学论文,每一篇论文都陈述了药物对疾病的影响。例如:

       Drug      Affect    Journal
       aspirin  downregulate  paper1
       aspririn downregulate  paper2
       aspirin  upregulate    paper3
       aspirin  neutral       paper4
       aspirin  downregulate  paper5
       aspririn upregulate    paper6
       iboruprofen  upregulate   paper7
       iboruprofen  upregulate   paper8
       iboruprofen  downregulate paper9
       other_drug     ...            ...

输出应如下所示:

Drug
aspirin

我想对df做一个筛选,只得到大多数论文中显示的下调疾病的药物,因此,如果阿司匹林有3篇论文说它下调,2篇论文说它上调,1篇论文说它具有中性作用,那么我们假设大多数证据表明其作用是下调。所以我想把阿司匹林放在我的肚子里。因此,iboruprofen不应该进入我的过滤df

我怎样才能把这个小组变成一个团队?谢谢你的帮助


Tags: 数据dfjournal疾病药物杂志科学论文drug
3条回答

按用药组和影响组的记录数进行计数

df_grouped = df.groupby(["Drug","Affect"], as_index=False).count()

输出:

    Drug         Affect        Journal
0   aspirin      downregulate    3
1   aspirin      neutral         1 
2   aspirin      upregulate      2
3   iboruprofen  downregulate    1
4   iboruprofen  upregulate      2

循环查看独特的药物清单并检查编号。如果下调>;上调,将此药物添加到结果列表中

result_drugs = []
for drug in np.unique(df["Drug"]:
    numberOfdownregulate = df_grouped[(df_grouped["Drug"] == drug) & (df_grouped["Affect"] == "downregulate")].Journal.values[0]
    numberOfupregulate = df_grouped[(df_grouped["Drug"] == drug) & (df_grouped["Affect"] == "upregulate")].Journal.values[0]
    result = numberOfdownregulate - numberOfupregulate
    
    if result > 0:
        result_drugs.append(drug)

最后,过滤原始数据帧

df[df["Drug"].isin(result_drugs)]

如果您只想拥有具有所需药物值的数据帧

pd.DataFrame(result_drugs, columns=["Drug"])

最终输出:

    Drug
0   aspirin

另一种选择是使用convtools库:

from convtools import conversion as c

# fmt: off
input_data = [
    {'Drug': 'aspirin', 'Affect': 'downregulate', 'Journal': 'paper1'},
    {'Drug': 'aspririn', 'Affect': 'downregulate', 'Journal': 'paper2'},
    {'Drug': 'aspirin', 'Affect': 'upregulate', 'Journal': 'paper3'},
    {'Drug': 'aspirin', 'Affect': 'neutral', 'Journal': 'paper4'},
    {'Drug': 'aspirin', 'Affect': 'downregulate', 'Journal': 'paper5'},
    {'Drug': 'aspririn', 'Affect': 'upregulate', 'Journal': 'paper6'},
    {'Drug': 'iboruprofen', 'Affect': 'upregulate', 'Journal': 'paper7'},
    {'Drug': 'iboruprofen', 'Affect': 'upregulate', 'Journal': 'paper8'},
    {'Drug': 'iboruprofen', 'Affect': 'downregulate', 'Journal': 'paper9'}
]
# fmt: on

converter = (
    c.group_by(c.item("Drug"))
    .aggregate(
        {
            "drug": c.item("Drug"),
            "down": c.ReduceFuncs.Count(
                where=c.item("Affect") == "downregulate"
            ),
            "up": c.ReduceFuncs.Count(where=c.item("Affect") == "upregulate"),
            "neutral": c.ReduceFuncs.Count(
                where=c.item("Affect") == "neutral"
            ),
        }
    )
    .filter(
        c.and_(
            c.item("down") > c.item("up"),
            c.item("down") > c.item("neutral"),
        )
    )
    # after the above the result is:
    #   [{"drug": "aspirin", "down": 2, "up": 1, "neutral": 1}]
    .iter(c.item("drug"))
    .as_type(list)
    .gen_converter()
)

assert converter(input_data) == ["aspirin"]

使用^{}^{}的更简单方法:

(
    df.groupby("Drug")
    .filter(lambda x: x["Affect"].value_counts().nlargest(1).index[0] == "downregulate")
    .get(["Drug"])
    .drop_duplicates()
)

values_counts返回Affect列中每个唯一值的计数。
nlargest(1)返回计数最高的单行
index返回一个包含最频繁项名称的数组

相关问题 更多 >