用元组或 geopy.location.Location 格式的外部数据覆盖 (geo)pandas (geo)dataframe 中的单个有条件选择的单元格
Overwrite a single conditionally selected cell in a (geo)pandas (geo)dataframe with external data in tuple or geopy.location.Location format
我从一个 pandas 历史地点数据框开始。我将一列地名传递给 geopy 进行地理编码。我提取坐标,并将它们变成点。我还将地理编码器返回的 geopy.location.Location 保存在一个列中以供进一步使用。如果我在整个 (geo)dataframe 上 运行 这一切似乎都工作正常。
当我想覆盖一些条目时,问题就出现了。例如,我想覆盖地理编码器尝试但未能正确定位 'Fargo N Dak'(历史缩写)的任何地方。我可以在一个现代化的地名上重新运行 地理编码器并提取数据,但我不知道如何将其插入原始 gdf。
import numpy as np
import pandas as pd
import geopandas as gpd
from geopy.extra.rate_limiter import RateLimiter
from geopy.geocoders import Nominatim
#set up Nominatim geocoder with geopy package with a user_agent (required) and a rate limiter
Ngeocoder0 = Nominatim(user_agent="aGeocoder")
Ngeocoder = RateLimiter(Ngeocoder0.geocode, min_delay_seconds=1)
#make some toy data
lst = ['Minneapolis MN', 'Fargo ND', 'Fargo N Dak']
df = pd.DataFrame(lst,columns =['rawPOB'])
df['_TEMP'] = df['rawPOB'].apply(lambda x: Ngeocoder(x, language='en',addressdetails=True))
df['rawGCcoords']=df['_TEMP'].apply(lambda x: (x.point[1], x.point[0]) if x else None)
df['rawGClong']=df['_TEMP'].apply(lambda x: (x.point[1]) if x else None)
df['rawGClat']=df['_TEMP'].apply(lambda x: (x.point[0]) if x else None)
gdf = gpd.GeoDataFrame(df, geometry=gpd.points_from_xy(df['rawGClong'], df['rawGClat']))
#so far so good, except Fargo N Dak is not recognized as Fargo North Dakota
#code just this place...
manualentry= Ngeocoder('Fargo North Dakota', language='en',addressdetails=True)
manualcoords=(manualentry.point[1], manualentry.point[0])
#... but here it all goes wrong when try to insert
gdf.loc[gdf.rawPOB == 'Fargo N Dak', '_TEMP'] = manualentry
gdf.loc[gdf.rawPOB == 'Fargo N Dak', 'rawGCcoords'] = manualcoords
#trying .at instead, and checking data type as in
gdf.dtypes
gdf.at[gdf.rawPOB == 'Fargo N Dak', 'rawGCcoords'] = manualcoords
# :(
我错过了什么?
谢谢。
P.S。在此示例中,我当然可以在尝试对其进行地理编码之前清理数据,但我正在尝试构建一个工作流,在该工作流中我可以使用映射的、第一个地理编码结果来寻找不太明显的错误。
我猜这是由于您索引 GeoDataFrame 的方式所致。
当你在做
gdf.loc[gdf.rawPOB == 'Fargo N Dak', '_TEMP']
你得到 pandas.Series in return (because you are using the boolean indexing 和 gdf.rawPOB == '..'
)。所以你不能做你正在尝试的任务(并且应该得到像 ValueError: Must have equal len keys and value when setting with an iterable
这样的错误,这对 that 没有帮助) .
我建议您使用 rawPOB
列重新索引 GeoDataFrame,然后您将能够轻松地 set/get 使用DataFrame.at
方法如下:
gdf.set_index('rawPOB', inplace=True)
gdf.at['Fargo N Dak', '_TEMP'] = manualentry
gdf.at['Fargo N Dak', 'rawGCcoords'] = manualcoords
完成后,如果需要,您可以像以前一样重置索引:
gdf.reset_index(inplace=True)
我接受了 mgc 的回答,因为它符合我的要求。谢谢!
然而,这是一位同事想出的替代方案,它可以满足我的要求,因为它可以处理多个相同 rawPOB
的实例,就像当我们像这样设置数据:
`lst = ['Minneapolis MN', 'Fargo ND', 'Fargo N Dak', 'Fargo N Dak']
#and continue with...
df = pd.DataFrame(lst,columns =['rawPOB'])
df['_TEMP'] = df['rawPOB'].apply(lambda x: Ngeocoder(x, language='en',addressdetails=True))
df['rawGCcoords']=df['_TEMP'].apply(lambda x: (x.point[1], x.point[0]) if x else None)
df['rawGClong']=df['_TEMP'].apply(lambda x: (x.point[1]) if x else None)
df['rawGClat']=df['_TEMP'].apply(lambda x: (x.point[0]) if x else None)
gdf = gpd.GeoDataFrame(df, geometry=gpd.points_from_xy(df['rawGClong'],
df['rawGClat']))
manualentry= Ngeocoder('Fargo North Dakota', language='en',addressdetails=True)
manualcoords=(manualentry.point[1], manualentry.point[0])
#NEW PART:
gdf['unique_id'] = pd.RangeIndex(stop=gdf.shape[0])
df_NOK = gdf.loc[gdf['rawPOB'] == 'Fargo N Dak' ]
for index, row in df_NOK.iterrows():
gdf.at[index, 'rawGCcoords'] = manualcoords
gdf.at[index, '_TEMP'] = manualentry`
我从一个 pandas 历史地点数据框开始。我将一列地名传递给 geopy 进行地理编码。我提取坐标,并将它们变成点。我还将地理编码器返回的 geopy.location.Location 保存在一个列中以供进一步使用。如果我在整个 (geo)dataframe 上 运行 这一切似乎都工作正常。
当我想覆盖一些条目时,问题就出现了。例如,我想覆盖地理编码器尝试但未能正确定位 'Fargo N Dak'(历史缩写)的任何地方。我可以在一个现代化的地名上重新运行 地理编码器并提取数据,但我不知道如何将其插入原始 gdf。
import numpy as np
import pandas as pd
import geopandas as gpd
from geopy.extra.rate_limiter import RateLimiter
from geopy.geocoders import Nominatim
#set up Nominatim geocoder with geopy package with a user_agent (required) and a rate limiter
Ngeocoder0 = Nominatim(user_agent="aGeocoder")
Ngeocoder = RateLimiter(Ngeocoder0.geocode, min_delay_seconds=1)
#make some toy data
lst = ['Minneapolis MN', 'Fargo ND', 'Fargo N Dak']
df = pd.DataFrame(lst,columns =['rawPOB'])
df['_TEMP'] = df['rawPOB'].apply(lambda x: Ngeocoder(x, language='en',addressdetails=True))
df['rawGCcoords']=df['_TEMP'].apply(lambda x: (x.point[1], x.point[0]) if x else None)
df['rawGClong']=df['_TEMP'].apply(lambda x: (x.point[1]) if x else None)
df['rawGClat']=df['_TEMP'].apply(lambda x: (x.point[0]) if x else None)
gdf = gpd.GeoDataFrame(df, geometry=gpd.points_from_xy(df['rawGClong'], df['rawGClat']))
#so far so good, except Fargo N Dak is not recognized as Fargo North Dakota
#code just this place...
manualentry= Ngeocoder('Fargo North Dakota', language='en',addressdetails=True)
manualcoords=(manualentry.point[1], manualentry.point[0])
#... but here it all goes wrong when try to insert
gdf.loc[gdf.rawPOB == 'Fargo N Dak', '_TEMP'] = manualentry
gdf.loc[gdf.rawPOB == 'Fargo N Dak', 'rawGCcoords'] = manualcoords
#trying .at instead, and checking data type as in
gdf.dtypes
gdf.at[gdf.rawPOB == 'Fargo N Dak', 'rawGCcoords'] = manualcoords
# :(
我错过了什么?
谢谢。
P.S。在此示例中,我当然可以在尝试对其进行地理编码之前清理数据,但我正在尝试构建一个工作流,在该工作流中我可以使用映射的、第一个地理编码结果来寻找不太明显的错误。
我猜这是由于您索引 GeoDataFrame 的方式所致。 当你在做
gdf.loc[gdf.rawPOB == 'Fargo N Dak', '_TEMP']
你得到 pandas.Series in return (because you are using the boolean indexing 和 gdf.rawPOB == '..'
)。所以你不能做你正在尝试的任务(并且应该得到像 ValueError: Must have equal len keys and value when setting with an iterable
这样的错误,这对 that 没有帮助) .
我建议您使用 rawPOB
列重新索引 GeoDataFrame,然后您将能够轻松地 set/get 使用DataFrame.at
方法如下:
gdf.set_index('rawPOB', inplace=True)
gdf.at['Fargo N Dak', '_TEMP'] = manualentry
gdf.at['Fargo N Dak', 'rawGCcoords'] = manualcoords
完成后,如果需要,您可以像以前一样重置索引:
gdf.reset_index(inplace=True)
我接受了 mgc 的回答,因为它符合我的要求。谢谢!
然而,这是一位同事想出的替代方案,它可以满足我的要求,因为它可以处理多个相同 rawPOB
的实例,就像当我们像这样设置数据:
`lst = ['Minneapolis MN', 'Fargo ND', 'Fargo N Dak', 'Fargo N Dak']
#and continue with...
df = pd.DataFrame(lst,columns =['rawPOB'])
df['_TEMP'] = df['rawPOB'].apply(lambda x: Ngeocoder(x, language='en',addressdetails=True))
df['rawGCcoords']=df['_TEMP'].apply(lambda x: (x.point[1], x.point[0]) if x else None)
df['rawGClong']=df['_TEMP'].apply(lambda x: (x.point[1]) if x else None)
df['rawGClat']=df['_TEMP'].apply(lambda x: (x.point[0]) if x else None)
gdf = gpd.GeoDataFrame(df, geometry=gpd.points_from_xy(df['rawGClong'],
df['rawGClat']))
manualentry= Ngeocoder('Fargo North Dakota', language='en',addressdetails=True)
manualcoords=(manualentry.point[1], manualentry.point[0])
#NEW PART:
gdf['unique_id'] = pd.RangeIndex(stop=gdf.shape[0])
df_NOK = gdf.loc[gdf['rawPOB'] == 'Fargo N Dak' ]
for index, row in df_NOK.iterrows():
gdf.at[index, 'rawGCcoords'] = manualcoords
gdf.at[index, '_TEMP'] = manualentry`