【问题标题】:Pandas groupby count with conditions熊猫分组计数条件
【发布时间】:2018-07-03 02:09:37
【问题描述】:

示例数据

给定以下数据框:

| feature | gene  |  target  | pos | 
| 1_1_1   | NRAS  |  AATTGG  | 60  |
| 1_1_1   | NRAS  |  TTGGCC  | 6   |
| 1_1_1   | NRAS  |  AATTGG  | 20  |
| 1_1_1   | KRAS  |  GGGGTT  |  0  |
| 1_1_1   | KRAS  |  GGGGTT  |  0  |
| 1_1_1   | KRAS  |  GGGGTT  |  0  |
| 1_1_2   | NRAS  |  CCTTAA  | 2   |
| 1_1_2   | NRAS  |  GGAATT  | 8   |
| 1_1_2   | NRAS  |  AATTGG  | 60  |

问题

对于每个特征,我想计算每个基因中出现了多少个目标,规则如下:

  • 如果目标仅出现在每个基因的一个位置(pos 列),则每次看到它的计数为 1
  • 如果同一目标出现在每个基因的多个位置,则计数为(位置计数/找到的总位置)
  • 总结每个特征的每个基因的总计数

到目前为止我做了什么

matches.groupby(["FeatureID", "gene"]).size().reset_index()

matches['multi_mapped'] = np.where(matches.groupby(["FeatureID", "gene", "target"]).pos.transform('nunique') > 1, "T", '')

这给了我一个数据框,其中出现在多个位置的目标被标记为真。现在我只需要弄清楚如何标准化计数。

期望的输出

| feature | gene  |  count
| 1_1_1   | NRAS  |   2
| 1_1_1   | KRAS  |   1
| 1_1_2   | NRAS  |   3

因此,在上面的 1_1_1 NRAS 示例中,AATTGG 在位置 60 和位置 20 处都存在,每个位置的计数均为 0.5。由于在一个位置找到了一次 TTGGCC,因此计数为 1。这使总计数为 2。

如果对于 1_1_1 NRAS TTGGCC 在同一位置找到 3 次,则每一次的计数为 1,总共 3 + .5 + .5 = 4。

解决方案需要检查出现在不同位置的相同目标,然后相应地调整计数,这就是我遇到困难的部分。我的最终目标是选择每组计数最高的基因。

【问题讨论】:

  • 我明白了,你能解释一下为什么 NRAS 是 3 吗?
  • 你能解释一下count at position/total positions found吗?如果 | 1_1_1 | NRAS | AATTGG | 20 | 被重复,所以 1_1_1 | NRAS 总共有 4 个条目,那么计数是多少? 2.5?
  • 您可以在groupby 中调用nunique() 而不是size(),但是我相信这会在@ALollz 描述的情况下出错。
  • 试试df.groupby(["feature", "gene", "target"]).nunique().groupby(level=[0,1]).feature.agg(sum)
  • 因此在示例中,在位置 60 和位置 20 都找到 AATTGG 时,每个位置的计数均为 0.5,而 TTGGCC 在一个位置找到一次,因此计数为 1。总计数为 2。如果在同一位置找到 3 次 TTGGCC,则每一个都将计数为 1,总共为 3。所有建议都没有解决检查出现在不同的职位。很抱歉造成混乱。

标签: python pandas pandas-groupby


【解决方案1】:

我不太清楚为什么第一行的计数应该是 2。你能试着解决这个问题吗:

import pandas as pd
feature = ["1_1_1"]*6 +["1_1_2"]*3
gene = ["NRAS"]*3+["KRAS"]*3+["NRAS"]*3
target = ["AATTGG","TTGGCC", "AATTGG"]+ ["GGGGTT"]*3 + ["CCTTAA", "GGGGTT", "AATTGG"]
pos = [60,6,20,0,0,0,2,8,60]
df = pd.DataFrame({"feature":feature,
                   "gene":gene,
                   "target":target,
                   "pos":pos})

df.groupby(["feature", "gene"])\
  .apply(lambda x:len(x.drop_duplicates(["target", "pos"])))

【讨论】:

  • 因此在示例中,在位置 60 和位置 20 都找到 AATTGG 时,每个位置的计数均为 0.5,而 TTGGCC 在一个位置找到一次,因此计数为 1。总计数为 2。如果在同一位置找到 3 次 TTGGCC,则每次计数为 1,总共为 3。
【解决方案2】:

好的,我想通了。如果有更有效的方法来做到这一点,我会全力以赴!

    # flag targets that are multi-mapped and add flag as new column
    matches['multi_mapped'] = np.where(matches.groupby(["FeatureID", "gene", "target"]).pos.transform('nunique') > 1, "T", '')

    # separate multi and non multi mapped reads using flag
    non = matches[matches["multi_mapped"] != "T"]\
        .drop("multi_mapped", axis=1)
    multi = matches[matches["multi_mapped"] == "T"]\
        .drop("multi_mapped", axis=1)

    # add counts to non multi mapped reads
    non = non.groupby(["FeatureID", "gene", "target"])\
        .count().reset_index().rename(columns={"pos":"count"})

    # add counts to multi-mapped reads with normaliztion 
    multi["count"] = multi.groupby(["FeatureID", "gene", "target"])\
          .transform(lambda x: 1/x.count())
    multi.drop("pos", axis=1, inplace=True)

    # join the multi and non back together
    counts = pd.concat([multi, non], axis=0)

【讨论】:

    猜你喜欢
    • 2020-01-25
    • 1970-01-01
    • 1970-01-01
    • 2018-04-29
    • 2017-03-21
    • 2017-01-30
    • 2023-01-03
    相关资源
    最近更新 更多