在pandas的groupby中保留无用列

3

我正在使用pandas处理一个中等大小的数据集,大约有600,000行。

它有三个“id”变量:“gene_id”,“gene_name”和“transcript_id”,然后是一些在运行时确定的数字列。

In [129]: df.head().todict()
{u'utr3_count': {8: 2.0, 30: 1.0, 29: 2.0, 6: 2.0, 7: 2.0}, 
 u'gene_id': {8: u'ENSG00000188157', 30: u'ENSG00000160087', 29: u'ENSG00000176022', 6: u'ENSG00000188157', 7: u'ENSG00000188157'}, 
 u'utr3_enrichment': {8: 2.1449912126499999, 30: 1.14988290398, 29: 1.0484234234200001, 6: 2.1449912126499999, 7: 2.1449912126499999},
 u'transcript_id': {8: u'ENST00000379370', 30: u'ENST00000450390', 29: u'ENST00000379198', 6: u'ENST00000379370', 7: u'ENST00000379370'},
 u'expression': {8: 0.13387876534027521, 30: 0.514855687606112, 29: 0.79126387397064091, 6: 0.13387876534027521, 7: 0.13387876534027521}, 
 u'gene_name': {8: u'AGRN', 30: u'UBE2J2', 29: u'B3GALT6', 6: u'AGRN', 7: u'AGRN'}}

我希望能够针对每个“transcript_id”获取复制品的平均值。但是,仅通过“transcript_id”进行分组处理意味着我会失去“gene_id”和“gene_name”的信息,因为它们被归类为无用的列。
如果我在三个列上进行分组,那么我将立即遇到MemoryError错误,即使在大型计算机(128GB)上也是如此,因为pandas尝试对三个列中的每个值的组合进行计算,尽管这绝对不是必要的:每个“transcript_id”映射到一个“gene_id”和一个“gene_name”。
有没有一种方法只对“transcript_id”进行分组处理,而不会失去其他列中的信息?
1个回答

2

简单解决方案:

transcript_idgene_idgene_name存储在一个单独的DataFrame中(例如metadata):

metadata = df[['transcript_id', 'gene_id', 'gene_name']].copy()
# .copy() is important!

使用 transcript_id 进行分组(使用groupby),并进行计算(例如使用agg_df)。完成计算后,将两个数据框合并在一起。
pd.merge(agg_df, metadata, how='left', on='transcript_id)

这个方法有效的原因是每个"transcript_id"都对应一个"gene_id"和一个"gene_name"。


替代方案:

读取文件(假设你正在从csv中读取),使用pd.read_csv(file_path, chunksize = <some integer, say 5e4>)按块读取。在所有三列上进行groupby操作(现在不会遇到MemoryError,因为你只读取了部分数据),并保持运行总数和运行计数。最后将总数除以计数即可。伪代码如下:

totals = pd.DataFrame()
counts = pd.DataFrame()
df = pd.read_csv(file_path, chunksize=5e4)
for chunk in df:
    grouped = chunk.groupby(['transcript_id', 'gene_id', 'gene_name'])
    totals = totals.add(grouped.sum())
    counts = counts.add(grouped.count())
means = totals/counts

这将适用于您需要以位和片段计算的一些度量,例如总和、计数、乘积、累积总和和乘积。但是像百分位数之类的任何东西都不行。
另一种解决方案(稍微困难一些):合并列transcript_idgene_idgene_name到另一列中,比如merged_id,并在merged_id上进行groupby。在计算结束时将该列拆分为组件。
附注:我建议使用简单的解决方案。

谢谢。我选择了简单的解决方案(至少部分原因是因为我没有从CSV中获取数据,而是从一个我无法控制的模块中获取)。感觉有点笨重,尤其是因为这是我经常要做的事情。我会等待看看是否还有其他东西出现。如果没有,我将标记为答案。 - Ian Sudbery

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接