Python - 基于值或条件列表的拾取数据

时间:2017-06-13 02:46:32

标签: python pandas

我有一个包含9列的数据集,我设法使用pandas提取了两个列(感谢Stack成员之前的帮助!)。现在,我的问题是:我有一个值列表,用于从数据集中提取并提取相应的值。提取的数据集如下所示:

Exp. m/z    Intensity
1000        2000
2000        3000
3000        4000
4000        5000

等等(每个数据集大约有500多行)。用于取件的清单如下:

mass
1200
1300

等等(拾取列表约200行)。每个质量值将用于计算上部和下部垃圾箱,它们将用于拾取Exp。来自数据集的m / z值。因此,例如,质量1200将被计算为1250(上部)和1150(下部),并且将从数据集中获取该范围内的任何内容,并且其相应的强度值是我想要的。如果没有拾取,我希望结果为空值,因为我认为0值会影响平均值和其他统计分析。

下面是我的代码,其中file是数据集,pickfile是拾取列表:

从pandas导入DataFrame

    import pandas as pd
    import numpy as np

    file = 'C09.xls'
    pickupfile = 'pickuplist.xlsx'

    xl = pd.ExcelFile(file)
    pl = pd.ExcelFile(pickupfile)

    plist = pd.read_excel(xl)
    pickuplist = pd.read_excel(pl)

    cmass = plist['Exp. m/z']
    height = plist['Intensity']


    plistcollect = pd.concat([cmass, height], axis=1)


    ppm = 150

    peak1upper = round(pickuplist*(1+ppm/1000000),4)

    peak1lower = round(pickuplist*(1-ppm/1000000),4)

    pickup = plistcollect[((plistcollect['Exp. m/z']>peak1lower) & (plistcollect['Exp. m/z'] < peak1upper))]
    print(pickup['Intensity'])

当我执行此代码时,我收到一条错误消息:ValueError:条件所需的布尔数组,而不是float64。我明白我的数据集是浮动值,所以你们有一些提示或提示/建议吗?

非常感谢!!

编辑: 忘记提到我的数据和两个限制(peak1lower&amp; peak1upper)是float64类型。

我也试过像isin那样的拾音器:

    pickup = plistcollect[plistcollect.isin(np.arange(peak1lower,peak1upper))]

2 个答案:

答案 0 :(得分:1)

如果索引数据框时有多个条件,则所有条件都在另一个括号内。

plistcollect[(plistcollect['Exp. m/z']>peak1lower) & (plistcollect['Exp. m/z'] < peak1upper)]

应该是

plistcollect[((plistcollect['Exp. m/z']>peak1lower) & (plistcollect['Exp. m/z'] < peak1upper))]

编辑:由于您需要在每个元素上执行它,您必须执行以下操作:

limit_df = pd.DataFrame([peak1lower['Exp. m/z'],peak1upper['Exp. m/z']], index=['lower','upper']).T
filtered_df = limit_df.apply(lambda x: ((plistcollect['Exp. m/z'] > x.lower) & (plistcollect['Exp. m/z'] < x.upper)), axis=1)

filtered_df会给你一个布尔数据框架,每一行都有True,False对应于属于质量列表给定元素的DataFrame条目。

更简单的方法是单独保存文件:

def filter_df(x):
    plistcollect[((plistcollect['Exp. m/z'] > x.lower) & (plistcollect['Exp. m/z'] < x.upper))].to_csv("test_%s.csv"%x.name)

limit_df.apply(lambda x: filter_df(x), axis=1)

答案 1 :(得分:1)

一种解决方案是创建一个新的DataFrame,将来自pickuplist的值作为索引,并从plist作为列

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

然后根据需要填充此DataFrame,例如,您可以只使用目标150ppm而不是使用abs进行此双边比较

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

这就是这样的

Exp. m/z    1000    2000    3000    4000
Intensity   2000    3000    4000    5000
mass                
1000    True    False   False   False
1200    False   False   False   False
1300    False   False   False   False

你可以轻松地用词汇理解来压缩

results = {i: list(s.index[s]) for i, s in matches.iterrows()}

返回pickuplistplist中每一行的每一行的dict条目,以(Exp. m/z, Intensity)形式出现{1000: [(1000, 2000)], 1200: [], 1300: []}

(Exp. m/z, Intensity)

如果您只想要results2 = {key for key, value in matches.any().iteritems() if value} 元组,则可以执行此操作

set

这给了{(1000, 2000)}

$ jq -c '.[] | map_values(.[1:]) | .k1,.k2' <<< "$json" | paste -d "," - -
"http://url",null