2017-08-01 80 views
2

我有一個數據框,其中包含具有不同名稱的一列。我從這些名字中提取功能並將它們存儲到字典中。然後,我想爲每個功能創建一個列,併爲每個名稱存儲值。我努力讓自己的循環正確。熊貓:循環遍歷每一行,提取特徵並創建新列

我的代碼:

import pandas as pd 

data = pd.DataFrame(['Mike', 'Ester', 'Sarah']) 
data.columns = ['name'] 

def get_features(name): 
    features = {} 
    features["firstletter"] = name[0].lower() 
    features["lastletter"] = name[-1].lower() 
    return features 

for name in data['name']: 
    features = get_features(name) 
    print features 
    for f,v in features.items(): 
     data[f] = v 
data.head() 

我得到:

name lastletter firstletter 
0 Mike h s 
1 Ester h s 
2 Sarah h s 

我需要:

name lastletter firstletter 
0 Mike e m 
1 Ester r e 
2 Sarah h s 

我明白爲什麼所有的名字得到姓氏值,但我想不出如何解決它。我可能會先爲所有功能創建新的標題,然後更新我的數據框,但我希望有一個更明智的方法。將感謝您的幫助!

編輯:我的功能比第一個/最後一個字母複雜得多。它含有大約20種不同的功能,所以我真的需要建立一個字典...

def get_features(name): 
    features = {} 
    features["firstletter"] = name[0].lower() 
    features["lastletter"] = name[-1].lower() 
    features["hythen"] = ("-" in name.lower()) 
    features["suffix"] = name[-2:].lower() 
    features["prefix"] = name[0:2].lower() 
    features["length"] = len(name) 
    for letter in 'abcdefghijklmnopqrstuvwxyz': 
     features["count(%s)" % letter] = name.lower().count(letter) 
     features["has(%s)" % letter] = (letter in name.lower()) 
    return features 
+0

答案已經更新。 – piRSquared

回答

3

我會做這種方式:

In [107]: data[['first_letter','last_letter']] = \ 
       data.name.str.lower().str.extract(r'^(.).*(.)$', expand=True) 

In [108]: data 
Out[108]: 
    name first_letter last_letter 
0 Mike   m   e 
1 Ester   e   r 
2 Sarah   s   h 

UPDATE:

In [127]: df.join(pd.DataFrame.from_records(df.apply(lambda x: get_features(x['name']), 
                axis=1).values, 
              index=df.index)) 
Out[127]: 
    name count(a) count(b) count(c) count(d) count(e) count(f) \ 
0 Mike   0   0   0   0   1   0 
1 Ester   0   0   0   0   2   0 
2 Sarah   2   0   0   0   0   0 

    count(g) count(h) count(i) ... has(v) has(w) has(x) has(y) \ 
0   0   0   1 ...  False False False False 
1   0   0   0 ...  False False False False 
2   0   1   0 ...  False False False False 

    has(z) hythen lastletter length prefix suffix 
0 False False   e  4  mi  ke 
1 False False   r  5  es  er 
2 False False   h  5  sa  ah 

[3 rows x 59 columns] 
+0

我的功能比第一個/最後一個字母複雜得多。它包含大約20個不同的功能,所以我真的需要建立一個字典... – aviss

+0

@aviss,我建議你發佈你的真實功能 - 它是有道理的,試圖找到一個矢量化的解決方案... – MaxU

+0

添加到這個問題。謝謝! – aviss

2

New Answer

更改您的功能只返回一個pd.Series並且僅執行一次lower

def get_features(name): 
    features = {} 
    name = name.lower() 
    features["firstletter"] = name[0] 
    features["lastletter"] = name[-1] 
    features["hythen"] = ("-" in name) 
    features["suffix"] = name[-2:] 
    features["prefix"] = name[0:2] 
    features["length"] = len(name) 
    for letter in 'abcdefghijklmnopqrstuvwxyz': 
     features["count(%s)" % letter] = name.count(letter) 
     features["has(%s)" % letter] = (letter in name) 
    return pd.Series(features) 

然後使用apply

data.join(data.name.apply(get_features)) 

    name count(a) count(b) count(c) count(d) count(e) count(f) count(g) count(h) count(i) ... has(v) has(w) has(x) has(y) has(z) hythen lastletter length prefix suffix 
0 Mike   0   0   0   0   1   0   0   0   1 ...  False False False False False False   e  4  mi  ke 
1 Ester   0   0   0   0   2   0   0   0   0 ...  False False False False False False   r  5  es  er 
2 Sarah   2   0   0   0   0   0   0   1   0 ...  False False False False False False   h  5  sa  ah 

老回答

data.assign(
    **data.name.str.lower().str.extract(
     '^(?P<firstletter>.).*(?P<lastletter>.)$', expand=True 
    ) 
) 

    name firstletter lastletter 
0 Mike   m   e 
1 Ester   e   r 
2 Sarah   s   h