【问题标题】:Speed up pandas dataframe lookup加快 pandas 数据框查找
【发布时间】:2016-07-10 02:42:26
【问题描述】:

我有一个包含大约 600,000 个地点的邮政编码、城市、州和国家/地区的 pandas 数据框。我们称之为 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

我已经尝试过 pandas 的 .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))

来自my_df的样本数据:

       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

【问题讨论】:

  • 你是怎么调用函数的?
  • 您是否尝试使用joinmerge 将您的DataFrame 加入zipdb?
  • @ayhan 我已经更新了问题。
  • @Brenbarn...这实际上是一个非常好的主意。我会试试的。

标签: python pandas dataframe


【解决方案1】:

使用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')
=> 

请注意,您可能需要扩展合并列和/或添加更多列以从 zips 数据框中复制。

【讨论】:

  • 感谢您的回答。但是,我还想带上longlat 列。现在这可能很容易做到吗?我还没有机会尝试。
  • Long, Lat 已被复制,但在屏幕截图中不可见。更改为使用通用列名作为合并键的可能更直接的方法。
  • 感谢您的更新。我来自 R...所以我很奇怪看到像 joinmerge 这样的方法工作得这么好(开玩笑,有点。哈哈)。再次感谢。
猜你喜欢
  • 2017-01-31
  • 2021-12-20
  • 2021-09-23
  • 2015-05-25
  • 1970-01-01
  • 1970-01-01
  • 2019-06-26
  • 1970-01-01
相关资源
最近更新 更多