2016-07-09 8 views
3

私は、郵便番号、都市、州、およそ600,000の場所のパンダデータフレームを持っています。さんはmy_dfそれを呼ぼうパンダのデータフレーム検索のスピードアップ

私が対応する経度緯度これらの場所のそれぞれのためを検索したいと思います。ありがたいことに、thisのデータベースがあります。このデータフレームをzipdbと呼ぶことにしましょう。

zipdbは、とりわけ、郵便番号、都市、州および国の列を持ちます。 zipdbですべての場所(郵便番号、市町村、州、国)を検索したいと思います。

def zipdb_lookup(zipcode, city, state, country): 

    countries_mapping = { "UNITED STATES":"US" 
        , "CANADA":"CA" 
        , "KOREA REP OF":"KR" 
        , "ITALY":"IT" 
        , "AUSTRALIA":"AU" 
        , "CHILE":"CL" 
        , "UNITED KINGDOM":"GB" 
        , "BERMUDA":"BM" 
    } 

    try: 
     slc = zipdb[ (zipdb.Zipcode == str(zipcode)) & 
        (zipdb.City == str(city).upper()) & 
        (zipdb.State == str(state).upper()) & 
        (zipdb.Country == countries_mapping[country].upper()) ] 

     if slc.shape[0] == 1: 
      return np.array(slc["Lat"])[0], np.array(slc["Long"])[0] 
     else: 
      return None 
    except: 
     return None 

私はパンダ.applyだけでなく、これを行うためのforループを試してみました。 どちらも非常に遅いです。私は行数が多いことを認識していますが、私は助けることはできませんが、より速いものが可能でなければならないと考えています。


zipdb = pandas.read_csv("free-zipcode-database.csv") #linked to above 

注:私もzibdbにこの変換を行ってきました:

zipdb["Zipcode"] = zipdb["Zipcode"].astype(str) 

関数コール:

#Defined a wrapper function: 
def lookup(row): 
    """ 

    :param row: 
    :return: 
    """ 

    lnglat = zipdb_lookup(
        zipcode = my_df["organization_zip"][row] 
       , city = my_df["organization_city"][row] 
       , state = my_df["organization_state"][row] 
       , country = my_df["organization_country"][row] 
    ) 

    return lnglat 

lnglat = list() 
for l in range(0, my_df.shape[0]): 
    # if l % 5000 == 0: print(round((float(l)/my_df.shape[0])*100, 2), "%") 
    lnglat.append(lookup(row = l)) 

からの

サンプルデータ:

 organization_zip organization_city organization_state organization_country 
0     60208   EVANSTON     IL United Sates 
1     77555   GALVESTON     TX United Sates 
2     23284   RICHMOND     VA United Sates 
3     53233   MILWAUKEE     WI United Sates 
4     10036   NEW YORK     NY United Sates 
5     33620    TAMPA     FL United Sates 
6     10029   NEW YORK     NY United Sates 
7     97201   PORTLAND     OR United Sates 
8     97201   PORTLAND     OR United Sates 
9     53715   MADISON     WI United Sates 
+0

どのように関数を呼び出していますか? – ayhan

+1

DataFrameとzipdbを結合するために 'join'または' merge'を使ってみましたか? – BrenBarn

+0

@ayhan質問を更新しました。 – lnNoam

答えて

4

merge()を使用すると、すべての行の関数を呼び出すよりもはるかに高速になります。フィールドタイプが一致すると文字列が取り除かれていることを確認します

# prepare your dataframe 
data['organization_zip'] = data.organization_zip.astype(str) 
data['organization_city'] = data.organization_city.apply(lambda v: v.strip()) 
# get the zips database 
zips = pd.read_csv('/path/to/free-zipcode-database.csv') 
zips['Zipcode'] = zips.Zipcode.astype(str) 
# left join 
# -- prepare common join columns 
zips.rename(columns=dict(Zipcode='organization_zip', 
         City='organization_city'), 
      inplace=True) 
# specify join columns along with zips' columns to copy 
cols = ['organization_zip', 'organization_city', 'Lat', 'Long'] 
data.merge(zips[cols], how='left') 
=> 

result

を使用すると、ジッパーのデータフレームからコピーするには、マージ列を拡張および/または複数の列を追加する必要があります。

+0

答えをありがとう。しかし、私はまた、「長い」、「緯」列を持って乗りたい。これは今簡単にできるでしょうか?私はまだ試してみる機会がありませんでした。 – lnNoam

+0

'Long'、' Lat'はすでにコピーされていましたが、スクリーンショットには表示されませんでした。マージキーに共通の列名を使用して、おそらくより直接的なアプローチに変更されました。 – miraculixx

+0

更新いただきありがとうございます。私はRから来ています。だから、 'join 'や' merge'のようなメソッドがうまく動作するのは奇妙です(ジョーク、一種の.ha)。再度、感謝します。 – lnNoam

関連する問題