Warning: file_get_contents(/data/phpspider/zhask/data//catemap/0/assembly/5.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Python 熊猫数据帧-如何分组和标记行_Python_Pandas - Fatal编程技术网

Python 熊猫数据帧-如何分组和标记行

Python 熊猫数据帧-如何分组和标记行,python,pandas,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.Excel

我有一大组数据,我想提取两列,我用下面的代码实现了这一点:

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
mass
1013.34
1079.3757
1095.3706
1136.3972
1241.4285
1257.4234
依此类推,并随附:

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数据帧的行被标记为文件名,这样我就可以对每个标记执行装箱操作?


作为补充说明,在定义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]
这为我提供了我想要的原始数据分析,如(请注意,此表的数字与上面的示例表不一致):

但是,我想规范化每个数据文件的强度值,因此我认为应该对每个文件的单独数据进行装箱。因此,为什么我要问是否有一种方法可以针对每个对应的文件标记plistcollect的行。还请注意,匹配过程必须在标准化之前完成。标准化是将每个强度值除以来自同一数据文件的强度值之和。使用上面的示例表,1013.33的标准化强度为:1000/(1000+2000),1013.35的标准化强度为:3000/(3000+4000)

我可以毫无问题地计算每个箱子中所有值的总和,但我似乎找不到一种方法来找到箱子之间强度值的总和,这些强度值对应于附加文件中的值

编辑:

我编辑代码以反映答案,并将“findex”添加到matches数据框中。现在,results3数据框架似乎包含文件名作为标记。组dataframe似乎也有标记值。问题是,如何通过标记名指定/分组

filetags = groups['Tag']
resulttable = pd.concat([filetags, groups['Exp. m/z'].mean(), average, CV], axis=1)
生成错误消息:无法连接非NDFrame对象

Edit2: pickuplist.xls文件包含一个名为“mass”的列,该列仅包含一个Exp.m/z值列表,我使用该列表从附加文件中获取Exp.m/z值(其中ppm为150,因此这些Exp.m/z值的差值在150 ppm以内(abs(mass-mass_from_file)/mass*1000000=150)。pickuplist.xls如下所示:

Number    Exp. m/z    Intensity
1         1013.33     1000
2         1257.52     2000
mass
1013.34
1079.3757
1095.3706
1136.3972
1241.4285
1257.4234

这些就是我所说的已知拾取列表,每个文件可能包含也可能不包含这些质量值。匹配定义实际上也来自堆栈溢出的用户之一。它用于迭代plistcollect,并选择那些与“质量”相差150 ppm以内的Exp.m/z值。

我认为您可以使用pa参数
输入:

这与:

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

编辑:

我想我明白了。需要先将
Tag
column添加到匹配项中,然后按
np分组。使用
Tag
column将
数字化:

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

plistcollect行似乎产生了一个错误,在.reset_index(level=1,drop=True)处显示意外缩进。因此我从pd.concat(dfs,keys=files_xls)中删除了“'),并在末尾添加了右括号(.reset_index()),现在给我一个错误消息,列表对象没有“reset_index”属性。你可以添加``或创建一个长行,然后就可以了。非常感谢你的回答。当我绞尽脑汁试图找出解决方案时,你能想出这段代码真是太神奇了。在任何情况下,这似乎是按预期将results3数据帧按标记分组。然后,当生成结果时,平均值、stdev和CV似乎不会被计算出来。此外,我需要将每个文件的每个元素(强度值)除以匹配后的强度值之和。所以对于test1.xls,我将对强度值求和,然后将每个强度除以和。有没有办法做到这一点?如果我问得太多,我很抱歉。我尝试删除groupby step组(包含np.digitize)的“标记”部分,并进行了计算,但现在标记如预期的那样消失了。很高兴可以提供帮助。我有个主意。我们可以通过电子邮件沟通吗?我的电子邮件在我的个人资料中。在
resulttable=pd.concat([filetags,groups['Exp.m/z'].mean(),average,CV],axis=1)之前有哪些内容是
print(type(filetags))
?上面写着pandas.core.groupby.SeriesGroupBy。在Resultable之后打印(filetags)不会产生错误,因此我将filetags连接到Resultable的方式一定有问题。我认为您缺少一些聚合函数,如
groups['Tag'].mean()
groups['Tag'].std()
hmm标记值是字符串值,如C09.xls-文件名。确定,我想帮助您编写另一个代码,但从
ppm=150
results3=matches.any().reset_index()[matches.any().values]的代码不理解。我也没有数据表列
mass
。。。你能解释更多并添加一些数据样本吗?
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
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