我怎样才能更快地将我的 for 循环工作转移到 pandas 应用功能?
How can I transfer my working for loop over to pandas much quicker apply functionality?
我有一个包含经度和纬度列的数据框。我需要在 geoPy 包的帮助下根据 long 和 lat 值获取该位置的县名。
longitude latitude housing_median_age total_rooms total_bedrooms \
0 -114.31 34.19 15.0 5612.0 1283.0
1 -114.47 34.40 19.0 7650.0 1901.0
2 -114.56 33.69 17.0 720.0 174.0
3 -114.57 33.64 14.0 1501.0 337.0
4 -114.57 33.57 20.0 1454.0 326.0
population households median_income median_house_value
0 1015.0 472.0 1.4936 66900.0
1 1129.0 463.0 1.8200 80100.0
2 333.0 117.0 1.6509 85700.0
3 515.0 226.0 3.1917 73400.0
4 624.0 262.0 1.9250 65500.0
我使用 for 循环成功了:
geolocator = geopy.Nominatim(user_agent='1234')
for index, row in df.iloc[:10, :].iterrows():
location = geolocator.reverse([row["latitude"], row["longitude"]])
county = location.raw['address']['county']
print(county)
数据集有 17,000 行,所以这应该是个问题吧?
所以我一直在想办法构建一个可以在 pandas.apply() 中使用的函数,以便更快地获得结果。
def get_zipcodes():
location = geolocator.reverse([row["latitude"], row["longitude"]])
county = location.raw['address']['county']
print(county)
counties = get_zipcodes()
我被卡住了,不知道如何在这里使用应用(或任何其他聪明的方法)。非常感谢帮助。
您代码中的 pandas 计算不太可能成为使用 geopy 时的速度瓶颈(参见 this answer 另一个 geopy 问题)。
但是,如果可能有大量行具有重复的 latitude, longitude
坐标,您可以使用 functools 中的 @cache
(或 @lru_cache(None)
)装饰器。
以下是如何在没有特殊缓存的情况下在数据帧上使用 apply()
:
df["county"] = df.apply(lambda row: geolocator.reverse([row["latitude"], row["longitude"]]).raw["address"]["county"], axis=1)
完整测试代码:
import geopy
geolocator = geopy.Nominatim(user_agent='1234')
import pandas as pd
df = pd.DataFrame({
'longitude':[-114.31,-114.47,-114.56,-114.57,-114.57],
'latitude':[34.19,34.40,33.69,33.64,33.57],
'housing_median_age':[15]*5,
'total_rooms':[1000]*5,
'total_bedrooms':[500]*5,
'population':[800]*5})
print(df)
df["county"] = df.apply(lambda row: geolocator.reverse([row["latitude"], row["longitude"]]).raw["address"]["county"], axis=1)
print(df)
输入:
longitude latitude housing_median_age total_rooms total_bedrooms population
0 -114.31 34.19 15 1000 500 800
1 -114.47 34.40 15 1000 500 800
2 -114.56 33.69 15 1000 500 800
3 -114.57 33.64 15 1000 500 800
4 -114.57 33.57 15 1000 500 800
输出:
longitude latitude housing_median_age total_rooms total_bedrooms population county
0 -114.31 34.19 15 1000 500 800 San Bernardino County
1 -114.47 34.40 15 1000 500 800 San Bernardino County
2 -114.56 33.69 15 1000 500 800 Riverside County
3 -114.57 33.64 15 1000 500 800 Riverside County
4 -114.57 33.57 15 1000 500 800 Riverside County
以下是如何使用装饰器缓存相同 latitude, longitude
坐标的结果(即避免多次到达 geopy 服务器):
from functools import cache
@cache
def bar(lat, long):
return geolocator.reverse([lat, long]).raw["address"]["county"]
def foo(row):
return bar(row["latitude"], row["longitude"])
df["county"] = df.apply(foo, axis=1)
我有一个包含经度和纬度列的数据框。我需要在 geoPy 包的帮助下根据 long 和 lat 值获取该位置的县名。
longitude latitude housing_median_age total_rooms total_bedrooms \
0 -114.31 34.19 15.0 5612.0 1283.0
1 -114.47 34.40 19.0 7650.0 1901.0
2 -114.56 33.69 17.0 720.0 174.0
3 -114.57 33.64 14.0 1501.0 337.0
4 -114.57 33.57 20.0 1454.0 326.0
population households median_income median_house_value
0 1015.0 472.0 1.4936 66900.0
1 1129.0 463.0 1.8200 80100.0
2 333.0 117.0 1.6509 85700.0
3 515.0 226.0 3.1917 73400.0
4 624.0 262.0 1.9250 65500.0
我使用 for 循环成功了:
geolocator = geopy.Nominatim(user_agent='1234')
for index, row in df.iloc[:10, :].iterrows():
location = geolocator.reverse([row["latitude"], row["longitude"]])
county = location.raw['address']['county']
print(county)
数据集有 17,000 行,所以这应该是个问题吧?
所以我一直在想办法构建一个可以在 pandas.apply() 中使用的函数,以便更快地获得结果。
def get_zipcodes():
location = geolocator.reverse([row["latitude"], row["longitude"]])
county = location.raw['address']['county']
print(county)
counties = get_zipcodes()
我被卡住了,不知道如何在这里使用应用(或任何其他聪明的方法)。非常感谢帮助。
您代码中的 pandas 计算不太可能成为使用 geopy 时的速度瓶颈(参见 this answer 另一个 geopy 问题)。
但是,如果可能有大量行具有重复的 latitude, longitude
坐标,您可以使用 functools 中的 @cache
(或 @lru_cache(None)
)装饰器。
以下是如何在没有特殊缓存的情况下在数据帧上使用 apply()
:
df["county"] = df.apply(lambda row: geolocator.reverse([row["latitude"], row["longitude"]]).raw["address"]["county"], axis=1)
完整测试代码:
import geopy
geolocator = geopy.Nominatim(user_agent='1234')
import pandas as pd
df = pd.DataFrame({
'longitude':[-114.31,-114.47,-114.56,-114.57,-114.57],
'latitude':[34.19,34.40,33.69,33.64,33.57],
'housing_median_age':[15]*5,
'total_rooms':[1000]*5,
'total_bedrooms':[500]*5,
'population':[800]*5})
print(df)
df["county"] = df.apply(lambda row: geolocator.reverse([row["latitude"], row["longitude"]]).raw["address"]["county"], axis=1)
print(df)
输入:
longitude latitude housing_median_age total_rooms total_bedrooms population
0 -114.31 34.19 15 1000 500 800
1 -114.47 34.40 15 1000 500 800
2 -114.56 33.69 15 1000 500 800
3 -114.57 33.64 15 1000 500 800
4 -114.57 33.57 15 1000 500 800
输出:
longitude latitude housing_median_age total_rooms total_bedrooms population county
0 -114.31 34.19 15 1000 500 800 San Bernardino County
1 -114.47 34.40 15 1000 500 800 San Bernardino County
2 -114.56 33.69 15 1000 500 800 Riverside County
3 -114.57 33.64 15 1000 500 800 Riverside County
4 -114.57 33.57 15 1000 500 800 Riverside County
以下是如何使用装饰器缓存相同 latitude, longitude
坐标的结果(即避免多次到达 geopy 服务器):
from functools import cache
@cache
def bar(lat, long):
return geolocator.reverse([lat, long]).raw["address"]["county"]
def foo(row):
return bar(row["latitude"], row["longitude"])
df["county"] = df.apply(foo, axis=1)