2016-04-08 16 views
3

Bir CSV dosyasındaki satırların üstbilgiler ve değerler içerdiğini ve hangi satırların çöp içerdiğini ve sonra da üstbilgileri/değerler satırlarını veri çerçevelerine aldığını anlamak için pythonic bir yol var mı?Python pandas: çoklu tablolarda csv'yi tekrarlı girişle oku

Python'a nispeten yeniyim ve bunu, bir bilimsel enstrümanın veri listesinden dışa aktarılan çoklu CSV'leri okumak için kullanıyorum ve diğer görevler için şu ana kadar CSV'lerle çalışırken, her zaman pandas kitaplığını kullanmaktan vazgeçtim. Bununla birlikte, bu CSV ihracatı, her bir cihazda kaydedilen "testlerin" sayısına bağlı olarak değişebilir.

Sütun üstbilgileri ve veri yapısı enstrümanlar arasında aynıdır, ancak değişebilen her testi ayıran bir "başlangıç" vardır. Eğer öyle olsaydı ben istediğiniz her zaman sabit bir uzunluk önsöz

blah blah here's a test and 
here's some information 
you don't care about 
even a little bit 
header1, header2, header3 
1, 2, 3 
4, 5, 6 

oh you have another test 
here's some more garbage 
that's different than the last one 
this should make 
life interesting 
header1, header2, header3 
7, 8, 9 
10, 11, 12 
13, 14, 15 

: Ben (iki test vardır, ancak potansiyel testlerinde herhangi bir sayı olabilir bu örneğin) şuna benzer yedeklemeler ile bitirmek Sadece atla parametresini kullanın, ancak başlangıç ​​değişken uzunluktur ve her testteki satır sayısı değişken uzunluktadır. Sonra her zamanki gibi pandalar ile işleyebilirsiniz

header1, header2, header3 
1, 2, 3 
4, 5, 6 
7, 8, 9 
10, 11, 12 
13, 14, 15 

:

Benim nihai hedef bütün testleri birleştirme ve benzeri bir şey ile sonuna kadar muktedir olduğunu.

denedim benim beklenen başlıklarla ilk satırı bulmak için aşağıdakileri yapın:

import csv 
import pandas as pd 

with open('my_file.csv', 'rb') as input_file:  
    for row_num, row in enumerate(csv.reader(input_file, delimiter=',')): 
     # The CSV module will return a blank list [] 
     # so added the len(row)>0 so it doesn't error out 
     # later when searching for a string 
     if len(row) > 0: 
      # There's probably a better way to find it, but I just convert 
      # the list to a string then search for the expected header 
      if "['header1', 'header2', 'header3']" in str(row): 
       header_row = row_num 

    df = pd.read_csv('my_file.csv', skiprows = header_row, header=0) 
    print df 

Bu başlıkları bulunması ilk satırı bulur çünkü sadece bir test var çalışır, ama tabii ki header_row değişken o başlığı bulur her ek süre güncellendiğini, yani örnekteki ben çıkışı ile sona yukarıda a kadar başlık/veri kümesi her bir örneğini eklemek için nasıl bulmaktan ben kaybolmadan ediyorum

header1 header2 header3 
0  7   8   9 
1  10  11   12 
2  13  14   15 

araştırmaya devam etmeden önce veri ağı üstbilgi/veri kümesinin sonraki örneği için g.

Ve büyük olasılıkla çok sayıda dosya ile uğraşırken, csv modülü ile bir kez daha pandas ile yeniden açmanız gerekiyor.

+0

Başlık nedir ve başlangıç ​​nedir? Eğer virgül, başlangıç ​​kısmında meydana geliyorsa, o zaman kayboldunuz ... – Chiel

+0

Başlıklar en azından adından da anlaşılacağı gibi, başlıkların 'header1, header2, header3' satırlarını içermesi ve gerçek veri kümesinin satır satırını hemen takip eden satırlar. Soru, başlık/veri içeren satırları "dilimlemek" ve bir veri çerçevesine dönüştürmek ve geri kalanını görmezden gelmektir. –

+0

Giriş bölümündeki virgülle çakışan Chiel ile anlaşma, risk altındadır. Verilerinizdeki herhangi bir satırda aynı sayıda virgül olmayacağınızı biliyorsanız, bunları filtrelemek için len (satır) kullanarak çıkış basittir. –

cevap

0

Bu program yardımcı olabilir. Temelde, csv.reader() nesnesinin etrafındaki sarıcıdır;

import pandas as pd 
import csv 
import sys 


def ignore_comments(fp, start_fn, end_fn, keep_initial): 
    state = 'keep' if keep_initial else 'start' 
    for line in fp: 
     if state == 'start' and start_fn(line): 
      state = 'keep' 
      yield line 
     elif state == 'keep': 
      if end_fn(line): 
       state = 'drop' 
      else: 
       yield line 
     elif state == 'drop': 
      if start_fn(line): 
       state = 'keep' 

if __name__ == "__main__": 

    df = open('x.in') 
    df = csv.reader(df, skipinitialspace=True) 
    df = ignore_comments(
     df, 
     lambda x: x == ['header1', 'header2', 'header3'], 
     lambda x: x == [], 
     False) 

    df = pd.read_csv(df, engine='python') 
    print df 
+0

Teşekkürler, Rob! Bence bu problemi çözüyor, ama merak ediyorum ... "df = pd.read_csv" (df, engine = 'python') 'satırında gerekli olan" motor "parametresini ayarlamak mı? –

0

Evet, bu Pandalar dayalı

Şimdi
import pandas as pd 
from StringIO import StringIO 

#define an example to showcase the solution 
st = """blah blah here's a test and 
here's some information 
you don't care about 
even a little bit 
header1, header2, header3 
1, 2, 3 
4, 5, 6 

oh you have another test 
here's some more garbage 
that's different than the last one 
this should make 
life interesting 
header1, header2, header3 
7, 8, 9 
10, 11, 12 
13, 14, 15""" 

# 1- read the data with pd.read_csv 
# 2- specify that you want to drop bad lines, error_bad_lines=False 
# 3- The header has to be the first row of the file. Since this is not the case, let's manually define it with names=[...] and header=None.  
data = pd.read_csv(StringIO(st), delimiter=",", names=["header1","header2", "header3"], error_bad_lines=False, header=None) 

# the trash will be loaded as follows 
# blah blah here's a test and  NaN   NaN 
# let's drop these rows 
data = data.dropna() 

# remove the rows which contain "header1","header2", "header3" 
mask = data["header1"].str.contains('header*') 
data = data[~mask] 
print data 

senin dataFrame böyle görünüyor (Bu soruyu cevaplamak için hızlı bir gösteri) yapmak için daha pythonic yolu vardır:

header1 header2 header3 
5  1  2  3 
6  4  5  6 
13  7  8  9 
14  10  11 12 
15  13  14  15 
+0

Teşekkürler MedAli. Bu başka bir Python başlangıç ​​sorusu olabilir, ama "~" sizin için ne yapar? "Data = data [~ mask]'? Bu konuda dokümantasyon bulmakta zorlanıyorum. –

+0

"~", maskenin içindeki değerlerin (yani bir np olan Boolean'ı (yanlış, true, false, false gibi) tuttuğu anlamına gelir. – MedAli

+0

@ TheJ, umarım bu, sorunuzu yanıtlarsa, lütfen cevabı kabul etmeyi düşün (http://meta.stackexchange.com/questions/5234/how-does-accepting-an-answer-work) – MedAli