2014-01-23 3 views
2

Я создаю столбец, чтобы добавить тег в некоторые строки и имеет рабочий код здесь:Python перебор панд более эффективна без цикла

import pandas as pd 
import numpy as np 
import re 

data=pd.DataFrame({'Lang':["Python", "Cython", "Scipy", "Numpy", "Pandas"], }) 
data['Type'] = "" 


pat = ["^P\w", "^S\w"] 

for i in range (len(data.Lang)): 
    if re.search(pat[0],data.Lang.ix[i]): 
     data.Type.ix[i] = "B" 

    if re.search(pat[1],data.Lang.ix[i]): 
     data.Type.ix[i]= "A" 


print data 

Есть ли способ, чтобы избавиться от этого for цикла? если это было numpy, есть функция arange что-то похожее на то, что я пытаюсь найти.

ответ

6

Это будет быстрее, чем применять SOLN (и кольцевой золь)

FYI: (это 0.13). В 0.12 вам нужно сначала создать столбец Type.

In [36]: data.loc[data.Lang.str.match(pat[0]),'Type'] = 'B' 

In [37]: data.loc[data.Lang.str.match(pat[1]),'Type'] = 'A' 

In [38]: data 
Out[38]: 
    Lang Type 
0 Python B 
1 Cython NaN 
2 Scipy A 
3 Numpy NaN 
4 Pandas B 

[5 rows x 2 columns] 

In [39]: data.fillna('') 
Out[39]: 
    Lang Type 
0 Python B 
1 Cython  
2 Scipy A 
3 Numpy  
4 Pandas B 

[5 rows x 2 columns] 

Вот некоторые тайминги:

In [34]: bigdata = pd.concat([data]*2000,ignore_index=True) 

In [35]: def f3(df): 
    df = df.copy() 
    df['Type'] = '' 
    for i in range(len(df.Lang)): 
     if re.search(pat[0],df.Lang.ix[i]): 
      df.Type.ix[i] = 'B' 
     if re.search(pat[1],df.Lang.ix[i]): 
      df.Type.ix[i] = 'A' 
    ....:    

In [36]: def f2(df): 
    df = df.copy() 
    df.loc[df.Lang.str.match(pat[0]),'Type'] = 'B' 
    df.loc[df.Lang.str.match(pat[1]),'Type'] = 'A' 
    df.fillna('') 
    ....:  

In [37]: def f1(df): 
    df = df.copy() 
    f = lambda s: re.match(pat[0], s) and 'A' or re.match(pat[1], s) and 'B' or '' 
    df['Type'] = df['Lang'].apply(f) 
    ....:  

Ваш оригинальный SOLN

In [41]: %timeit f3(bigdata) 
1 loops, best of 3: 2.21 s per loop 

Прямая индексация

In [42]: %timeit f2(bigdata) 
100 loops, best of 3: 17.3 ms per loop 

Применить

In [43]: %timeit f1(bigdata) 
10 loops, best of 3: 21.8 ms per loop 

Вот еще один более общий метод, который немного быстрее, и проблема более полезна , так как вы можете комбинировать шаблоны, скажем, groupby, если хотите.

In [107]: pats 
Out[107]: {'A': '^P\\w', 'B': '^S\\w'} 

In [108]: concat([df,DataFrame(dict([ (c,Series(c,index=df.index)[df.Lang.str.match(p)].reindex(df.index)) for c,p in pats.items() ]))],axis=1) 
Out[108]: 
     Lang A B 
0 Python A NaN 
1 Cython NaN NaN 
2 Scipy NaN B 
3 Numpy NaN NaN 
4 Pandas A NaN 
5 Python A NaN 
6 Cython NaN NaN 

45 Python A NaN 
46 Cython NaN NaN 
47 Scipy NaN B 
48 Numpy NaN NaN 
49 Pandas A NaN 
50 Python A NaN 
51 Cython NaN NaN 
52 Scipy NaN B 
53 Numpy NaN NaN 
54 Pandas A NaN 
55 Python A NaN 
56 Cython NaN NaN 
57 Scipy NaN B 
58 Numpy NaN NaN 
59 Pandas A NaN 
     ... ... ... 

[10000 rows x 3 columns] 

In [106]: %timeit concat([df,DataFrame(dict([ (c,Series(c,index=df.index)[df.Lang.str.match(p)].reindex(df.index)) for c,p in pats.items() ]))],axis=1) 
100 loops, best of 3: 15.5 ms per loop 

Этот кадр Гвозди на серии для каждого из скороговорки, что ставит письмо в правильном положении (и NaN в противном случае).

Создать серию этого письма

Series(c,index=df.index) 

Выберите спички из него

Series(c,index=df.index)[df.Lang.str.match(p)] 

индексирование ставят NaN, где значение не в индексе

Series(c,index=df.index)[df.Lang.str.match(p)].reindex(df.index)) 
+0

Вау спасибо. Один вопрос, если у меня много шаблонов, есть эффективная функция для итерации через них? – user3084006

+0

Я добавил еще один (лучше солон) – Jeff

3

Вы можете сделать обе классификации с одним лямбда:

f = lambda s: re.match(pat[0], s) and 'A' or re.match(pat[1], s) and 'B' or '' 

затем использовать apply, чтобы получить "Тип"

data.Type = data.Lang.apply(f) 

выход:

 Lang Type 
0 Python A 
1 Cython 
2 Scipy B 
3 Numpy 
4 Pandas A 

Редактировать: Может быть, после сравнения не сравнялись. Если вы хотите ускорить процесс, чем просто избежать компиляции регулярного выражения

def f1(df): 
    df = df.copy() 
    f = lambda s: re.match(pat[0], s) and 'A' or re.match(pat[1], s) and 'B' or '' 
    df['Type'] = df['Lang'].apply(f) 
    return df 

def f1_1(df): 
    df = df.copy() 
    re1, re2 = re.compile(pat[0]), re.compile(pat[1]) 
    f = lambda s: re1.match(s) and 'A' or re2.match(s) and 'B' or '' 
    df.Type = df.Lang.apply(f) 
    return df 

bigdata = pd.concat([data]*2000,ignore_index=True) 

оригинал Применение:

In [18]: %timeit f1(bigdata) 
10 loops, best of 3: 23.1 ms per loop 

пересмотренная Применение:

In [19]: %timeit f1_1(bigdata) 
100 loops, best of 3: 6.65 ms per loop 
Смежные вопросы