我正在处理一个包含大约900行的特殊csv文件
0.0165824,+,ESI,ms1,-,line,40.0000-700.0000,663,35.2072 12,37.7808 11,38.0004 17,39.1216 18,39.1755 11,40.0806 12,41.4810 11,42.0517 19
值以逗号“,
”分隔。但是,从第9列开始,该文件包含我实际感兴趣的元组值。我想使用pandas
来完成这项工作。由于我使用这种方法的不同行的列数不相等:
import csv
import pandas as pd
with open('test.csv') as fb:
reader = csv.reader(fb)
df = pd.DataFrame().from_records(reader)
这会产生一个包含元组作为字符串的数据框。从那时起,我首先计划使用第一列作为外部索引创建多索引数据帧,并使用每个元组值的内部索引(第9列向前)。或者作为替代,使用第一列作为键在字典中包含多个数据帧。
目前,我正在使用此代码:
import csv
import numpy as np
raw_data = 'test.csv'
result = {}
lower_mass = 200
upper_mass = 300
with open(raw_data, 'rb') as f:
reader = csv.reader(f, delimiter=',')
for row in reader:
mz = []
i = []
key = float(row[0])
data = row[8:]
for d in data:
tup = d.split(" ")
mass = float(tup[0])
intens = float(tup[1])
if (mass > lower_mass) & (mass < upper_mass):
mz.append(float(tup[0]))
i.append(float(tup[1]))
result[key] = {"mz": mz, "I": i}
这将生成一个字典,其中包含值mz
和I
的两个列表,使用第一列作为键,为清楚起见,还删除了一些我不想存储的列(1-7)。我还应用过滤器来收缩数据(lower_mass和upper_mass)。这些操作本来是在数据框上进行的。
我不高兴,因为我失去了以矢量化方式进行数据处理的能力。最后,数据应该用于在不同的键中找到一些mz
值。
是否有更好/更快的解决方案?
答案 0 :(得分:1)
我想我明白你要做什么,如果不让我知道,我会编辑我的答案。
我接近这个的方法是在pandas中使用melt和str.split函数。融化将“宽”数据转换为“长”数据,这将允许您拆分元组并最终过滤数据。
使用此CSV文件,其中包含宽度不同的行以及从第8列开始的所有相关数据。
0.0165824,+,ESI,ms1,-,line,40.0000-700.0000,663,35.2072 12,37.7808 11,38.0004 17,39.1216 18,39.1755 11,40.0806 12,41.4810 11,42.0517 19
0.0165825,+,ESI,ms1,-,line,40.0000-700.0000,663,35.2072 12,37.7808 11,38.0004 17,39.1216 18,39.1755 11,40.0806 12,41.4810 11,42.0517 19,40.0806 12,41.4810 11,42.0517 19
0.0165826,+,ESI,ms1,-,line,40.0000-700.0000,663,35.2072 12,37.7808 11,38.0004 17,39.1216 18,39.1755 11
代码
import pandas as pd
import numpy as np
df = pd.read_csv('s.csv', header=None, names=np.arange(19)) # Read in CSV, use names to handle different CSV row widths
df = df.drop(np.arange(1,8), axis="columns") # Drop columns 1:7
df = pd.melt(df, id_vars=[0], value_vars=np.arange(8, df.shape[1])) # Melt data columns 8:N
# df.head()
# 0 variable value
# 0 0.016582 8 35.2072 12
# 1 0.016583 8 35.2072 12
# 2 0.016583 8 35.2072 12
# 3 0.016582 9 37.7808 11
# 4 0.016583 9 37.7808 1
df[['mass','I']] = df.value.str.split(" ", expand=True).apply(pd.to_numeric, errors='coerce') # Split value column and apply change from string to numeric datatype; assign split to mass and I columns
df = df.rename(columns={0: "key", 'variable':'csv_column'}).drop('value', axis='columns') # Rename column zero to key and drop string column
# df.head()
# key csv_column mass I
#0 0.016582 8 35.2072 12
#1 0.016583 8 35.2072 12
#2 0.016583 8 35.2072 12
#3 0.016582 9 37.7808 11
#4 0.016583 9 37.7808 11
现在您可以使用pandas进行过滤和排序。请注意,CSV中的“空白”值将转换为pandas中的NaN
;这不会显示在上面的df.head()
输出中。这是在errors='coerce'
函数中使用pd.to_numeric
的结果。