2016-07-08 38 views
3

因此,我已这个pandas.Dataframepandas.apply期望输出形状(传递的值的形状为(x,),指数暗示(X,Y))

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

其中 - 是对象,开始是初始坐标和结束是每个元素的最终坐标。

我定义了这个函数来计算表中所有间隔的联合,在这个例子中它应该总和为[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) 

与它未能在下列数据框:

   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(尽管有一些人在它的另一个数据框崩溃后的环路。

所以这个解决方案是多余的和愚蠢的。 MY HYPOTHESIS是这个特定数据框中的行数匹配一些奇怪的参数(比如列数或类似的东西),这使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] 

所以我认为错误与熊猫试图迫使我以前的数据帧,并从输出一个与一些兼容性做的,但我很惊讶,对于大多数DataFrames它工作得很好!

回答

1

方法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) 
+0

为什么使用元组()不是Python的?我被告知永远不要在熊猫上迭代,这不是非常优化的。 – Nico

+0

@Nico是的,矢量化的代码比循环要快得多。但是在这里,'apply'只是遍历行,不能被cython化或向量化。而且,创建未使用的数据帧还有一些开销,并且使用union1d进行多次调用,这会多次调用。 – ptrj

相关问题