python - pandas DataFrame - 如何对行进行分组和标记

标签 python pandas

我有一大组数据,我想提取两列,我设法用下面的代码做到了这一点:

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 列表文件夹中的每个文件包含 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]

它拾取那些 Exp。落在 ppm 差异 (150 ppm) 范围内的 m/z 值,仍然采用与 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 之间的强度值总和.

编辑:

我编辑了代码以反射(reflect)答案,同时将“findex”添加到匹配数据框中。现在 results3 数据框似乎包含文件名作为标签。 groups dataframe 似乎也有 Tag 值。问题是,如何通过标签名称指定/分组?

filetags = groups['Tag']
resulttable = pd.concat([filetags, groups['Exp. m/z'].mean(), average, CV], axis=1)

产生错误消息:无法连接非 NDFrame 对象。

编辑2: pickuplist.xls 文件包含一个名为“mass”的列,其中只有一个 Exp 列表。我用来提取获得的 Exp 的 m/z 值。来自附加文件的 m/z 值(其中 ppm 150 进来,所以那些 Exp.m/z 值落在 150 ppm 差异内(abs(质量 - mass_from_file)/质量* 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 值。

最佳答案

我想你可以在 concat 中使用参数 keys :

dfs = []
for f in files_xls:
    dfs = pd.read_excel(f, 'Sheet1')[['Exp. m/z','Intensity']]
    dfs.append(data)

它等同于:

dfs = [pd.read_excel(f, 'Sheet1')[['Exp. m/z','Intensity']] for f in files_xls]

plistcollect = pd.concat(dfs, keys=files_xls) \
                 .reset_index(level=1, drop=True) \
                 .rename_axis('Tag') \
                 .reset_index()
print (plistcollect)
         Tag  Exp.m/z  Intensity
0  test1.xls  1013.33       1000
1  test1.xls  1257.52       2000
2  test2.xls  1013.35       3000
3  test2.xls  1257.61       4000

编辑:

我想我明白了。需要先将 Tag 列添加到匹配项,然后通过 np.digitizeTag 列进行分组:

print (plist)
         Tag  Exp. m/z  Intensity
0  test1.xls      1000       2000
1  test1.xls      1000       1500
2  test1.xls      2000       3000
3  test2.xls      3000       4000
4  test2.xls      4000       5000
5  test2.xls      4000       5500

pickup = pd.DataFrame({'mass':[1000,1200,1300, 4000]})
print (pickup)
   mass
0  1000
1  1200
2  1300
3  4000

matches = pd.DataFrame(index=pickup['mass'], 
                       columns = plist.set_index(list(plist.columns)).index, 
                       dtype=bool)

ppm = 150
for index, tags, exp_mass, intensity in plist.itertuples():
    matches[(tags, exp_mass)] = abs(matches.index - exp_mass) / matches.index < ppm / 1e6

print (matches)
Tag       test1.xls               test2.xls              
Exp. m/z       1000          2000      3000   4000       
Intensity      2000   1500   3000      4000   5000   5500
mass                                                     
1000           True   True  False     False  False  False
1200          False  False  False     False  False  False
1300          False  False  False     False  False  False
4000          False  False  False     False   True   True

results3 = matches.any().reset_index(name='a')[matches.any().values]
print (results3)
         Tag  Exp. m/z  Intensity     a
0  test1.xls      1000       2000  True
1  test1.xls      1000       1500  True
4  test2.xls      4000       5000  True
5  test2.xls      4000       5500  True

bins = np.arange(900, 3000, 1)
groups = results3.groupby([np.digitize(results3['Exp. m/z'], bins), 'Tag'])

resulttable = groups.agg({'Intensity':['mean','std'], 'Exp. m/z': 'mean'})
resulttable.columns = resulttable.columns.map('_'.join)
resulttable['CV'] = resulttable['Intensity_std'] / resulttable['Intensity_mean'] * 100
d = {'Intensity_mean':'Average','Exp. m/z_mean':'Exp. m/z'}
resulttable = resulttable.reset_index().rename(columns=d) \
                          .drop(['Intensity_std', 'level_0'],axis=1)
print (resulttable)
         Tag  Average  Exp. m/z         CV
0  test1.xls     1750      1000  20.203051
1  test2.xls     5250      4000   6.734350

关于python - pandas DataFrame - 如何对行进行分组和标记,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/44584311/

相关文章:

python - 添加数据透视表列和索引作为 xticks 和 yticks

python - 属性错误: module transformers has no attribute TFGPTNeoForCausalLM

Python循环遍历一系列变量

python - 如何在箱形图2上绘制来自不同数据帧的数据 - Python

python - 将 JSON 行导入 Pandas

Python Pandas 将一列中的 NaN 替换为第二列相应行中的值

python - 根据下拉菜单中的键更新标签 Tkinter Python

python - Google 云端硬盘断点续传上传失败

python - 构建列表列表的字典理解 : referencing the current value for a key during comprehension

python - 如何检查列中的所有值是否满足 Data Frame 中的条件?