python - pandas.apply 期望输出形状(传递值的形状是(x,),索引暗示(x,y))

标签 python numpy pandas apply bioinformatics

所以我有这个 pandas.Dataframe

C1    C2     C3    C4    C5    Start    End    C8
A     1      -      -     -     1        4     -
A     2      -      -     -     6        10    -
A     3      -      -     -     11       14    -
A     4      -      -     -     15       19    -

其中 - 是对象,Start 是初始坐标,end 是每个元素的最终坐标。

我定义了这个函数来计算表中所有区间的并集,在这个例子中应该总和为 [1,19]-{5}(基本上是一个包含所有包含元素的 numpy 数组)。

def coverage(table):
    #return a dataframe with the coverage of each individual peptide in a protein 
    interval = (table.apply(lambda row : range(int(row['Start']),int(row['End'])+1),axis=1))] 
    #if there is only one peptide, return the range between its start and end positions 
    if len(table) == 1: return asarray(range(int(table['Start']),int(table['End'])+1)) 
    #if there are more, unite all the intervals 
    if len(table) > 1: 
            return reduce(union1d,(list(interval)))

所以我将该函数迭代地应用于多个 DataFrame(第一个是 A,然后是 B、C 等)。问题是对于某些表,这会失败并给出此错误:

Traceback (most recent call last):
File "At_coverage.py", line 37, in <module>
covdir[prot] = coverage(data)
File "At_coverage.py", line 21, in coverage
interval = (table.apply(lambda row : range(int(row['Start']),int(row['End'])+1),axis=1))
File "/usr/lib/python2.7/dist-packages/pandas/core/frame.py", line 3312, in apply
return self._apply_standard(f, axis, reduce=reduce)
File "/usr/lib/python2.7/dist-packages/pandas/core/frame.py", line 3417, in _apply_standard
result = self._constructor(data=results, index=index)
File "/usr/lib/python2.7/dist-packages/pandas/core/frame.py", line 201, in __init__
mgr = self._init_dict(data, index, columns, dtype=dtype)
File "/usr/lib/python2.7/dist-packages/pandas/core/frame.py", line 323, in _init_dict
dtype=dtype)
File "/usr/lib/python2.7/dist-packages/pandas/core/frame.py", line 4473, in _arrays_to_mgr
return create_block_manager_from_arrays(arrays, arr_names, axes)
File "/usr/lib/python2.7/dist-packages/pandas/core/internals.py", line 3760, in create_block_manager_from_arrays
construction_error(len(arrays), arrays[0].shape[1:], axes, e)
File "/usr/lib/python2.7/dist-packages/pandas/core/internals.py", line 3732, in construction_error
passed,implied))
ValueError: Shape of passed values is (7,), indices imply (7, 8)

失败的 DataFrame 如下:

               Protein           Peptide  \
11106  sp|Q75W54|EBM_ARATH           GJDGFJK   
11107  sp|Q75W54|EBM_ARATH           GJDGFJK   
11108  sp|Q75W54|EBM_ARATH  JJDPHJVSTFFDDYKR   
11109  sp|Q75W54|EBM_ARATH  JJDPHJVSTFFDDYKR   
11110  sp|Q75W54|EBM_ARATH         JNGEPJFJR   
11111  sp|Q75W54|EBM_ARATH         JNGEPJFJR   
11112  sp|Q75W54|EBM_ARATH         JNGEPJFJR   

                                        Fraction  Count  \
11106  AT_indark_IEX_fraction_18a_20150422.uniprot-pr...      2   
11107  AT_indark_IEX_fraction_21a_20150422.uniprot-pr...      2   
11108  AT_indark_IEX_fraction_18a_20150422.uniprot-pr...      2   
11109  AT_indark_IEX_fraction_19a_20150422.uniprot-pr...      1   
11110  AT_indark_IEX_fraction_19a_20150422.uniprot-pr...      2   
11111  AT_indark_IEX_fraction_22a_20150422.uniprot-pr...      2   
11112  AT_indark_IEX_fraction_25a_20150422.uniprot-pr...      2   

                                            Sequence  Start  End  Length  
11106  MAEIGKTVLDFGWIAARSTEVDVNGVQLTTTNPPAISSESRWMEAA...    577  584     944  
11107  MAEIGKTVLDFGWIAARSTEVDVNGVQLTTTNPPAISSESRWMEAA...    577  584     944  
11108  MAEIGKTVLDFGWIAARSTEVDVNGVQLTTTNPPAISSESRWMEAA...    210  226     944  
11109  MAEIGKTVLDFGWIAARSTEVDVNGVQLTTTNPPAISSESRWMEAA...    210  226     944  
11110  MAEIGKTVLDFGWIAARSTEVDVNGVQLTTTNPPAISSESRWMEAA...    344  353     944  
11111  MAEIGKTVLDFGWIAARSTEVDVNGVQLTTTNPPAISSESRWMEAA...    344  353     944  
11112  MAEIGKTVLDFGWIAARSTEVDVNGVQLTTTNPPAISSESRWMEAA...    344  353     944  

[7 rows x 8 columns]

为了让它工作,我将第三行替换为

    interval = (table.apply(lambda row : range(int(row['Start']),int(row['End'])+4),axis=1)).apply(lambda row: row[:-3])

我注意到它也适用于除 +1 以外的任何其他数字(尽管对于其他一些数字,它会在循环稍后的另一个 DataFrame 处崩溃。

所以这个解决方案是多余的和愚蠢的。我的假设是这个特定数据框中的行数与一些奇怪的参数(比如列数或类似的东西)相匹配,这使得 Pandas 试图简化某些东西然后它崩溃了。

我制作了一个简化版本的程序,它也适用于多个起点和终点:

def multicov(row):
    intervals = []
    for i in range(len(row['Start'])):
    #print data
            intervals.append((range(int(row['Start'][i]),int(row['End'][i])+1)))
    return reduce(union1d,intervals)


dir = {'Start':[[1,7],[14]],
    'End':[[5,10],[18]]}

df = DataFrame(dir,columns=['Start','End'])
print df
print df.apply(multicov,axis=1)

在这种情况下,它给出了同样的错误

ValueError: Shape of passed values is (2,), indices imply (2, 2)

但有趣的是,如果我从函数返回两个元素(以便它匹配 2,2)它表现良好。

return reduce(union1d,intervals),'foobar'

Start      End
0  [1, 7]  [5, 10]
1    [14]     [18]

[2 rows x 2 columns]
0    ([1, 2, 3, 4, 7, 8, 9, 10], foobar)
1         ([14, 15, 16, 17, 18], foobar)
dtype: object

如果我将输出指定为列表,

return [reduce(union1d,intervals),'foobar']

它将前面的列名与输出相匹配!

Start      End
0  [1, 7]  [5, 10]
1    [14]     [18]

[2 rows x 2 columns]
               Start     End
0  [1, 2, 3, 4, 7, 8, 9]  foobar
1       [14, 15, 16, 17]  foobar

[2 rows x 2 columns]

所以我认为该错误与 Pandas 试图强制我以前的 DataFrame 和输出的 DataFrame 之间存在某种兼容性有关,但令我惊讶的是,对于大多数 DataFrame,它运行良好!

最佳答案

方法 apply(func) 遍历行(或列)并将 func 应用于每一行。 func 的结果然后被放入一个新的数据框或一个系列中。如果 func 返回一个标量值(例如 sum 所做的),那么它就是一个系列。如果它返回一个数组、列表或系列,那么结果是一个维度框架,具体取决于该数组的长度。

在您的代码中,func 返回不同长度(间隔长度)的数组,这些数组不能放在一个框架中。因此错误。 (实际上,您遇到的第一个错误可能是这样的:ValueError: could not broadcast input array from shape (5) into shape (9)。)

线

return reduce(union1d,intervals),'foobar'

返回一个元组,所以 apply 的结果是一个系列。和

return [reduce(union1d,intervals),'foobar']

返回一个长度为 2 的列表。因此,您在这里得到一个 n x 2 数据框。维度与输入数据框一致,因此 pandas 假定您想要修改原始框架的单元格(类似于应用 lambda x: 2*x)并且它保留列名。

一个可能有效的解决方案是将函数中的 range(x, y) 更改为 tuple(range(x, y))。但它既不高效也不 pythonic。更好的方法是用行上的显式循环替换 apply,例如:

def coverage(table):
    intervals = []
    for row in table.itertuples():
        intervals += list(range(row.Start, row.End + 1))
    return np.unique(intervals)

关于python - pandas.apply 期望输出形状(传递值的形状是(x,),索引暗示(x,y)),我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/38274014/

相关文章:

python - 如何将常规 numpy 数组转换为记录数组?

python - 从间隔列表中确定值的位置(综合解决方案)

python - 如何将宽数据帧转换为长数据帧

python - 当没有重复项时,pandas 中索引重复错误

python - 取消聚合 Pandas 中的字符串值字段

python - 用 Pandas 计算每行的 NaN

Python : Celery, 如何让它在后台运行?

python - Django - 如何将异步任务队列与 celery 和 redis 一起使用

python - grep、awk、bash 和 friend ?有什么工具可以处理这些数据吗?

python - 如何使用表单上的按钮向 QTabWidget 添加选项卡?