【发布时间】:2017-06-17 14:03:00
【问题描述】:
我有大量数据要提取两列,我使用下面的代码设法做到了:
import pandas as pd
import numpy as np
import os
pickupfile = 'pickuplist.xls'
path = os.chdir('some path')
files = os.listdir(path)
files_xls = [f for f in files if f[-3:] == 'xls']
df = pd.DataFrame()
pl = pd.ExcelFile(pickupfile)
pickuplist = pd.read_excel(pl)
df = [pd.read_excel(f, 'Sheet1')[['Exp. m/z','Intensity']] for f in files_xls]
plistcollect = pd.concat(df, keys=files_xls)\
.reset_index(level=1, drop=True)\
.rename_axis('Tag')\
.reset_index()
pk list 文件夹中的每个文件包含 10 列,上面的代码从文件中提取两列到 plistcollect 数据帧中。对我来说不利的是文件拉取迭代将数据附加到先前数据的底部。数据如下:
Number Exp. m/z Intensity
1 1013.33 1000
2 1257.52 2000
以此类推,并带有附加:
Number Exp. m/z Intensity
1 1013.33 1000
2 1257.52 2000
3 1013.35 3000
4 1257.61 4000
其中 1~2 来自第一个文件,3~4 来自第二个文件,依此类推。每个文件都有不同数量的行或索引(即文件 1 有 400 行,文件 2 有 501 行等),这导致我的代码出现一些问题。所以问题是,有没有办法标记每个文件,以便在迭代文件以追加到 plistcollect 时,用文件名标记 plistcollect DataFrame 的行,以便我可以为每个文件执行分箱标签?
附带说明,在定义 plistcollect 之后,我执行匹配:
ppm = 150
matches = pd.DataFrame(index=pickuplist['mass'], columns=plistcollect.set_index(list(plistcollect.columns)).index, dtype=bool)
for index, findex, exp_mass, intensity in plistcollect.itertuples():
matches[findex, exp_mass] = abs(matches.index - exp_mass) / matches.index < ppm / 1e6
results = {i: list(s.index[s]) for i, s in matches.iterrows()}
results2 = {key for key, value in matches.any().iteritems() if value}
results3 = matches.any().reset_index()[matches.any().values]
其中拾取那些经验。 m/z 值在 ppm 差异 (150 ppm) 内,仍与 plistcollect 格式相同。然后我通过以下方式使用 np.digitize 进行分箱:
bins = np.arange(900, 3000, 1)
groups = results3.groupby(np.digitize(results3['Exp. m/z'], bins))
stdev = groups['Intensity'].std()
average = groups['Intensity'].mean()
CV = stdev/average*100
resulttable = pd.concat([groups['Exp. m/z'].mean(),average,CV], axis=1)
resulttable.columns.values[1] = 'Average'
resulttable.columns.values[2] = 'CV'
resulttable.to_excel('test.xls', index=False)
这为我提供了我想要的原始数据分析(请注意,此表的数字与上面的示例表不对应):
Exp. m/z Average CV
1013.32693 582361.5354 13.49241757
1257.435414 494927.0904 12.45206038
但是,我想对每个数据文件的强度值进行标准化,所以我认为应该对每个文件的单独数据进行分箱。因此,为什么我要问是否有一种方法可以针对每个相应的文件标记 plistcollect 的行。另请注意,匹配过程必须在规范化之前完成。归一化是将每个强度值除以来自同一数据文件的强度值之和。使用上面的示例表,1013.33 的归一化强度为:1000/(1000+2000),1013.35 的归一化强度为:3000/(3000+4000)。
我可以毫无问题地计算每个 bin 中所有值的总和,但我似乎无法找到一种方法来找到对应于附加文件中值的来源的 bin 之间的强度值总和.
编辑:
我编辑了代码以反映答案,并将“findex”添加到匹配数据框。现在 results3 数据框似乎包含文件名作为标签。组数据框似乎也有标签值。问题是,如何按标签名称指定/分组?
filetags = groups['Tag']
resulttable = pd.concat([filetags, groups['Exp. m/z'].mean(), average, CV], axis=1)
产生以下错误消息:无法连接非 NDFrame 对象。
编辑2: Picklist.xls 文件包含一个名为“mass”的列,其中包含一个 Exp 列表。我用来拾取获得的 Exp 的 m/z 值。附加文件中的 m/z 值(其中 ppm 150 出现,因此那些 Exp. m/z 值在 150 ppm 差异范围内(abs(mass - mass_from_file)/mass*1000000 = 150)。pickuplist.xls 看起来像:
mass
1013.34
1079.3757
1095.3706
1136.3972
1241.4285
1257.4234
这些就是我所说的已知拾取列表,每个文件可能包含也可能不包含这些质量值。匹配定义实际上也来自 Stack Overflow 的一位用户。它用于迭代 plistcollect,并选择那些 Exp。与“质量”相差 150 ppm 以内的 m/z 值。
【问题讨论】:
-
在
resulttable = pd.concat([filetags, groups['Exp. m/z'].mean(), average, CV], axis=1)之前是print (type(filetags))吗? -
它说 pandas.core.groupby.SeriesGroupBy。结果表后的 print(filetags) 不会产生错误,因此我将文件标签连接到结果表的方式一定有问题。
-
我认为你错过了一些聚合函数,例如
groups['Tag'].mean()或groups['Tag'].std() -
hmm 标签值是字符串值,例如 C09.xls - 文件名。
-
好的,我想帮助您使用另一个代码,但是从
ppm = 150到results3 = matches.any().reset_index()[matches.any().values]的代码不明白。另外我没有数据表单列mass...你能解释更多并添加一些数据样本吗?