python 3.熊猫:罕见的数据形式扰乱了正常的统计分析



我在分析一些生物信息学数据(在Pandas中)时遇到了一个问题,其中一种罕见但有效的数据形式混淆了所述数据的统计分析。这就是数据(在数据帧group_PrEST中)通常看起来的样子:

PrEST ID    Gene   pepCN1   pepCN2   pepCN3
HPRR1       CD38     5298    10158      NaN
HPRR2       EGFR    79749    85793   117274
HPRR6       EPS8    68076    62305    66599
HPRR6       EPS8      NaN      NaN   141828

下面是处理这些数据的一些代码(PrEST_stats是另一个收集统计数据的数据帧):

PrEST_stats['R1'] = group_PrESTs['pepCN1'].median()
PrEST_stats['R2'] = group_PrESTs['pepCN2'].median()
PrEST_stats['R3'] = group_PrESTs['pepCN3'].median()
PrEST_stats['CN'] = PrEST_stats[['R1', 'R2', 'R3']].median(axis=1)
PrEST_stats['CN'] = PrEST_stats['CN'].round()
PrEST_stats['STD'] = PrEST_stats[['R1', 'R2', 'R3']].std(axis=1, ddof=1)
PrEST_stats['CV'] = PrEST_stats['STD'] / 
    PrEST_stats[['R1', 'R2', 'R3']].mean(axis=1) * 100

它的作用是:

  1. 为每个基因分别计算pepCN1、pepCN2、pepCN3列的中位数
  2. 计算(1)
  3. 结果的中位数
  4. 计算(1)
  5. 结果的标准差和变异系数

在大多数情况下,这很好:

  • 基因CD38的上述数据将给出两个中值(R1R2)与它们在pepCN1 &pepCN2(因为只有一行基因CD38)
  • 基因EPS8会以类似的方式赋予R1R2,但会赋值根据中两个值的中位数为R3计算另一个值pepCN3列的两行

在这两种情况下,统计数据将以正确的方式计算。统计数据在第一轮"减少"数据(即计算第一个中位数)之后计算的事实是:三个数据列代表技术复制,在"合并"它们在最终统计值中之前应该单独处理。

在数据看起来像这样的极少数情况下出现问题:

PrEST ID    Gene   pepCN1   pepCN2   pepCN3
HPRR9      PTK2B     4972      NaN      NaN
HPRR9      PTK2B    17095      NaN      NaN

脚本将在这里将两个pepCN1值减少到单个中位数,忽略没有值(即没有来自复制2和3的数据)用于计算其他数据列的统计信息的事实。脚本将运行并给出正确的CN值(中位数),但标准偏差和变异系数的统计数据将被忽略(即显示为NaN)。

在这种情况下,我希望脚本以某种方式看到将数据列减少到一个值(第一个中位数)不是要走的路。本质上,我希望它跳过计算第一个中位数(这里是:R1),只计算两行pepCN1的统计信息。有办法做到这一点吗?提前感谢!

[EDIT: new problems]

好的,现在代码看起来是这样的:

indexer = PrESTs.groupby('PrEST ID').median().count(1) == 1
one_replicate = PrESTs.loc[PrESTs['PrEST ID'].isin(indexer[indexer].index)]
multiple_replicates = PrESTs.loc[~PrESTs['PrEST ID'].isin(indexer[indexer]
                                                          .index)]
all_replicates = {0: one_replicate, 1: multiple_replicates}
# Calculations (PrESTs)
PrEST_stats_1 = pd.DataFrame()
PrEST_stats_2 = pd.DataFrame()
all_stats = {0: PrEST_stats_1, 1: PrEST_stats_2}
for n in range(2):
    current_replicate = all_replicates[n].groupby(['PrEST ID', 'Gene names'])
    current_stats = all_stats[n]
    if n == 1:
        current_stats['R1'] = current_replicate['pepCN1'].median()
        current_stats['R2'] = current_replicate['pepCN2'].median()
        current_stats['R3'] = current_replicate['pepCN3'].median()
    else:
        current_stats['R1'] = current_replicate['pepCN1'] # PROBLEM (not with .median())
        current_stats['R2'] = current_replicate['pepCN2'] # PROBLEM (not with .median())
        current_stats['R3'] = current_replicate['pepCN3'] # PROBLEM (not with .median())
    current_stats['CN'] = current_stats[['R1', 'R2', 'R3']].median(axis=1)
    current_stats['CN'] = current_stats['CN'].round()
    current_stats['STD'] = current_stats[['R1', 'R2', 'R3']].std(axis=1, ddof=1)
    current_stats['CV'] = current_stats['STD'] / 
        current_stats[['R1', 'R2', 'R3']].mean(axis=1) * 100
    current_stats['STD'] = current_stats['STD'].round()
    current_stats['CV'] = current_stats['CV'].round(1)
PrEST_stats = PrEST_stats_1.append(PrEST_stats_2)

…我又有新问题了将这两种情况划分为两个新的dataframe就可以了,现在我想做的是在上面的for循环中稍微不同地处理它们。我已经检查了我评论# PROBLEM的行,我在那里添加了.median(),也给了我与我以前得到的相同的结果-即其余的代码工作,而不是当我试图离开数据的时候!这是我得到的错误:

Traceback (most recent call last):
  File "/Users/erikfas/Dropbox/Jobb/Data - QE/QEtest.py", line 110, in <module>
    current_stats['R1'] = current_replicate['pepCN1']
  File "/Users/erikfas/anaconda/envs/py33/lib/python3.3/site-packages/pandas/core/frame.py", line 1863, in __setitem__
    self._set_item(key, value)
  File "/Users/erikfas/anaconda/envs/py33/lib/python3.3/site-packages/pandas/core/frame.py", line 1938, in _set_item
    self._ensure_valid_index(value)
  File "/Users/erikfas/anaconda/envs/py33/lib/python3.3/site-packages/pandas/core/frame.py", line 1915, in _ensure_valid_index
    raise ValueError('Cannot set a frame with no defined index '
ValueError: Cannot set a frame with no defined index and a value that cannot be converted to a Series

我试图找出这里出了什么问题,但我毫无头绪。是不是我必须对数据做点什么而不是.median(),而不是什么都不做?还是别的什么?

[EDIT]:修改了上面代码中的一些行(在else语句中):

temp.append(current_replicate['pepCN1'])
temp.append(current_replicate['pepCN2'])
temp.append(current_replicate['pepCN3'])
current_stats = pd.concat(temp)

…其中temp是一个空列表,但随后我得到以下错误:

File "/Users/erikfas/Dropbox/Jobb/Data - QE/QEtest.py", line 119, in <module>
    temp2 = pd.concat(temp)
  File "/Users/erikfas/anaconda/envs/py33/lib/python3.3/site-packages/pandas/tools/merge.py", line 926, in concat
    verify_integrity=verify_integrity)
  File "/Users/erikfas/anaconda/envs/py33/lib/python3.3/site-packages/pandas/tools/merge.py", line 986, in __init__
    if not 0 <= axis <= sample.ndim:
  File "/Users/erikfas/anaconda/envs/py33/lib/python3.3/site-packages/pandas/core/groupby.py", line 295, in __getattr__
    return self._make_wrapper(attr)
  File "/Users/erikfas/anaconda/envs/py33/lib/python3.3/site-packages/pandas/core/groupby.py", line 310, in _make_wrapper
    raise AttributeError(msg)
AttributeError: Cannot access attribute 'ndim' of 'SeriesGroupBy' objects, try using the 'apply' method

这不是我可以用对象分组吗?

试试这个

In [28]: df
Out[28]: 
      id   gene     p1     p2      p3
0  HPRR1   CD38   5298  10158     NaN
1  HPRR2   EGFR  79749  85793  117274
2  HPRR6   EPS8  68076  62305   66599
3  HPRR6   EPS8    NaN    NaN  141828
4  HPRR9  PTK2B   4972    NaN     NaN
5  HPRR9  PTK2B  17095    NaN     NaN
[6 rows x 5 columns]

按id字段分组(我认为这是您想要的有效中位数)。算出如果该组中有任何无效的中位数(例如,合并该组后出现nan)。

In [53]: df.groupby('id').median().count(1)
Out[53]: 
id
HPRR1    2
HPRR2    3
HPRR6    3
HPRR9    1
dtype: int64

你想删除只有1个有效值的组,ok!

In [54]: df.groupby('id').median().count(1) == 1
Out[54]: 
id
HPRR1    False
HPRR2    False
HPRR6    False
HPRR9     True
dtype: bool
In [30]: indexers = df.groupby('id').median().count(1) == 1

将它们从原始数据中取出(然后重新运行)或填充或其他。

In [67]: df.loc[~df.id.isin(indexers[indexers].index)]
Out[67]: 
      id  gene     p1     p2      p3
0  HPRR1  CD38   5298  10158     NaN
1  HPRR2  EGFR  79749  85793  117274
2  HPRR6  EPS8  68076  62305   66599
3  HPRR6  EPS8    NaN    NaN  141828
[4 rows x 5 columns]

对于您的总体计算,您可以这样做。这比附加到一个初始空的DataFrame更可取。

results = []
for r in range(2):
    # do the calcs from above to generate say df1 and df2
    results.append(df1)
    results.append(df2)
# concatenate the rows!
final_result = pd.concat(results)

最新更新