【问题标题】:Pandas groupby subtract a reference row from the rest of rows in group same lengthPandas groupby 从组中相同长度的其余行中减去参考行
【发布时间】:2022-01-29 01:40:52
【问题描述】:

尝试从 biorep 中的所有其他事物中减去参考组 cq,使用 pandas 或我猜是一般 python 的分析组。如果可能,紧凑或雄辩。这在 R 中非常简单,但在这里无法弄清楚

biorep  well          sample    assay   cq
  1      C1            spA      MSGN1   10
  1      C2            spA      MSGN1   15
  1      C3            spA      MSGN1   20
  1      C4            ref      MSGN1   5
  2      C1            spB      MSGN1   12 
  2      C2            spB      MSGN1   15
  2      C3            spB      MSGN1   20
  2      C4            ref      MSGN1   4

我想按 biorep 和分析进行分组。对于这些组中的每一个,从组中的其他事物中减去代表。所以我应该得到这样的结果。 l.

biorep  well          sample    assay   cq  delta
  1      C1            spA      MSGN1   10       5
  1      C2            spA      MSGN1   15       10
  1      C3            spA      MSGN1   20       15
  1      C4            ref      MSGN1   5.        0
  2      C1            spB      MSGN1   12        8
  2      C2            spB      MSGN1   15       11
  2      C3            spB      MSGN1   20       16
  2      C4            ref      MSGN1   4         0

我知道这应该很容易,但即使有来自 stackoverflow 的建议,我也遇到了麻烦。我尝试使用这个建议,这是我找到的最重要的建议Subtracting group specific value from rows in pandas,但无济于事。我得到了这些NaN。所有其他建议似乎都不相关,或者在谷歌上搜索这个问题时遇到了麻烦。有人在这里有想法吗?

def func(grp):
    ref =   grp.loc[grp['sample'] == 'No Spacer Control','cq']
    grp['delta'] =   grp[grp['sample'] == 'No Spacer Control']['cq'] - ref
    return grp

summry.groupby(['biorep','assay']).apply(func)
   biorep     sample       assay        cq         delta
         1    No Spacer Control HPRT    25.237209       0.0
         1      spMSGN1_1       HPRT    25.632444       NaN
         1      spMSGN1_10      HPRT    25.298286       NaN
         1      spMSGN1_11      HPRT    25.130593       NaN
         1      spMSGN1_2       PRT     25.371607       NaN

【问题讨论】:

  • 请不要将代码/数据/错误消息作为图片发布。将格式化文本直接发布在 SO 上。
  • 为什么不用plate列进组?
  • 对不起,我不应该包含它。在这个特定的实验中它不相关。
  • 修复不再是图像
  • 我摆脱了盘子。我的例子有点令人困惑。我认为它现在已经和谐了

标签: python pandas


【解决方案1】:

您可以从 ref 值创建数据框并将其与原始数据框合并:

df_ref = df.loc[df['sample'] == 'ref', ['biorep', 'assay', 'cq']]

df = df.merge(df_ref, how='left', on=['biorep', 'assay'], suffixes=('', '_ref'))
df['delta'] = df['cq'] - df['cq_ref']

【讨论】:

  • 谢谢!这确实有效。我也希望看到 groupby 逻辑的一些东西,因为我想在组内进行很多其他操作,这个例子是他们的一个很好的代理。
【解决方案2】:

根据记录的顺序,您可以从组中减去最后一个cq,只要您在分组中包含plate

df['delta'] = df.groupby(['biorep','assay', 'plate'])['cq'].apply(lambda x: x.sub(x.iloc[-1]))

输出

   plate well  biorep sample  assay  cq  delta
0      1   C1       1    spA  MSGN1  10      5
1      1   C2       1    spA  MSGN1  15     10
2      1   C3       1    spA  MSGN1  20     15
3      1   C4       1    ref  MSGN1   5      0
4      2   C1       1    spB  MSGN1  12      8
5      2   C2       1    spB  MSGN1  15     11
6      2   C3       1    spB  MSGN1  20     16
7      2   C4       1    ref  MSGN1   4      0

【讨论】:

  • 有不需要顺序的逻辑吗?我不认为我将能够始终确保订单,因为这可能是脆弱的。参考名称是我可以 100% 确定的。不过,我很感激我总是可以对其进行排序。
  • 感谢您的回答。很有帮助。
【解决方案3】:
编辑后

更新

试试:

compute_delta = lambda x: x.loc[x['sample'].ne('ref'), 'cq'] \
                           .sub(x.loc[x['sample'].eq('ref'), 'cq'].squeeze())

df['delta'] = df.groupby(['biorep', 'assay'], as_index=False) \
                .apply(compute_delta).droplevel(0).reindex(df.index, fill_value=0)
print(df)

# Output
   biorep well sample  assay  cq  delta
0       1   C1    spA  MSGN1  10      5
1       1   C2    spA  MSGN1  15     10
2       1   C3    spA  MSGN1  20     15
3       1   C4    ref  MSGN1   5      0
4       2   C1    spB  MSGN1  12      8
5       2   C2    spB  MSGN1  15     11
6       2   C3    spB  MSGN1  20     16
7       2   C4    ref  MSGN1   4      0

【讨论】:

  • @SuperCal123。我的版本不需要任何ref 行的顺序组...
  • 谢谢你,我会测试一下。并重新分配复选标记等。我非常感谢所有不同的方法。学到很多希望这也能帮助其他人。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2020-09-24
  • 2018-06-16
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多