2017-08-15 14 views
2

基本的に、次のコードは、別の文字列(この場合は 'JKLMNOPQR')の列 'a'の文字の位置を返します。この例では、列 'b'はすべての行で同じ値を持ちますが、異なる値を持つことができます。パンダのある列の値の位置を求めるベクトル化

ベクター化された方法がありますか?

ベクトル化されません
frame = pd.DataFrame({'a' : ['L', '}', 'P']}) 
frame['b']='}JKLMNOPQR' 
frame['c'] = frame.apply(lambda row: row.b.find(row.a), axis=1) 
frame 

    a  b   c 
0 L }JKLMNOPQR 3 
1 } }JKLMNOPQR 0 
2 P }JKLMNOPQR 7 

答えて

3

が、zipを使用して高速化ソリューション:

lframe1 = pd.concat([frame]*1000) 
lframe2 = pd.concat([frame]*1000) 

%timeit lframe1['c'] = lframe1.apply(lambda row: row.b.find(row.a), axis=1) 
# 10 loops, best of 3: 77.7 ms per loop 

%timeit lframe2['c'] = [b.find(a) for a, b in zip(lframe2.a, lframe2.b)] 
# 1000 loops, best of 3: 1.4 ms per loop 

lframe1.c.eq(lframe2.c).all() 
# True 
2

あなたはassign

0123でこれをラップ np.core.defchararray

np.core.defchararray.find(frame.b.values.astype(str), frame.a) 

array([3, 0, 7]) 

からfindを使用することができます

enter image description here

pir1 = lambda d: d.assign(c=np.core.defchararray.find(d.b.values.astype(str), d.a.values.astype(str))) 
pir2 = lambda d: d.assign(c=(np.array([list(x) for x in d.b.values.tolist()]) == d.a.values[:, None]).argmax(1)) 
psi = lambda d: d.assign(c=[b.find(a) for a, b in zip(d.a, d.b)]) 
jso = lambda d: d.assign(c=d.apply(lambda row: row.b.find(row.a), axis=1)) 

results = pd.DataFrame(
    index=pd.Index([10, 30, 100, 300, 1000, 3000, 10000, 30000]), 
    columns='pir1 pir2 psi jso'.split() 
) 

for i in results.index: 
    d = pd.concat([frame] * i, ignore_index=True) 
    for j in results.columns: 
     stmt = '{}(d)'.format(j) 
     setp = 'from __main__ import d, {}'.format(j) 
     results.set_value(i, j, timeit(stmt, setp, number=10)) 

results.plot(loglog=True) 
以下Psidomの zip
コード@打ちにくい
frame.assign(c=np.core.defchararray.find(frame.b.values.astype(str), frame.a)) 

    a   b c 
0 L }JKLMNOPQR 3 
1 } }JKLMNOPQR 0 
2 P }JKLMNOPQR 7 

タイミング

関連する問題