我在分析一些生物信息学数据(在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
它的作用是:
- 为每个基因分别计算pepCN1、pepCN2、pepCN3列的中位数
- 计算(1) 结果的中位数
- 计算(1) 结果的标准差和变异系数
在大多数情况下,这很好:
- 基因
CD38
的上述数据将给出两个中值(R1
和R2
)与它们在pepCN1
&pepCN2
(因为只有一行基因CD38
) - 基因
EPS8
会以类似的方式赋予R1
和R2
,但会赋值根据中两个值的中位数为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)