2017-05-17 42 views
1

我處理含有約900行數據結構,用於使用python

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 

的值由逗號「,」分離的特有csv文件異構CSV。然而,從第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} 

這會生成包含兩個列表使用第一列作爲重點和清晰的價值觀mzI字典也下降了一些列我不想存儲(1-7)。我還應用一個過濾器來收縮數據(lower_mass和upper_mass)。這些操作將在數據幀上執行。

我不開心,因爲我失去了以矢量化方式進行數據操作的能力。最後,應該使用這些數據在不同的鍵中找到一些mz值。

有沒有更好的/更快的解決方案?

回答

1

我想我明白你想要做什麼,如果不讓我知道,我會編輯我的答案。

我接觸到的方式是使用熊貓中的meltstr.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 

現在你可以用大熊貓篩選和排序。請注意,CSV中的「空白」值將轉換爲熊貓中的NaN;這在上面的df.head()輸出中沒有顯示。這是在pd.to_numeric函數中使用errors='coerce'的結果。

+0

謝謝你的努力! @Josh。由於列的長度不同,熊貓不會讀取文件。解決方法是在讀入文件之前查找最大列數並添加'name'屬性。但是,剩餘的代碼工作正常。 – Fourier

+1

嗨@Fourier,我已經使用names參數更新了我的答案,您還可以只提供一個數組給'names',其寬度將比數據更寬,然後僅從數據框中過濾'NaNs'。 – Josh