从 1600 万+ lat/long 获取 FIPS 块代码
Posted
技术标签:
【中文标题】从 1600 万+ lat/long 获取 FIPS 块代码【英文标题】:Getting FIPS block codes from 16million+ lat/long 【发布时间】:2020-02-18 01:50:01 【问题描述】:这似乎是一个常见问题,没有任何易于理解/易于实施的答案。很多人引用FCC API,但我不知道如何使用 API,也没有找到一个简单的解释来帮助我解决这种情况。我可以做 R 代码,我可以做 Python(如果它很简单的话),但似乎应该有一些相对简单的资源来获取带有 lat/long 列的 .csv(或类似的),并取回 FIPS 代码(在块组级别,来自 2010 年人口普查)。
潜在的解决方案(以及我的问题):
This github 我相信查询 old FCC API,它已退役。无论哪种方式,当我在给出的示例上运行它时,它都会抛出错误Error in fromJSON(content, handler, default.size, depth, allowComments, : invalid JSON input
。此外,我想知道如果映射超过 1600 万个坐标会如何
This SO question 在几行上效果很好,我已经在我只需要几千个查询的情况下实现了它,但是我得到了错误 Error in curl::curl_fetch_memory(url, handle = handle) : Timeout was reached: Send failure: Connection was reset
和 Error in call_geolocator_latlon(row["GE_LATITUDE_2010"], row["GE_LONGITUDE_2010"]) : Service Unavailable (HTTP 503)
,我认为这是由于我的数据太大了。
here 的解决方案似乎乍一看对我来说不是最好的,因为它涉及下载 shapefile,这似乎效率低下,但因为我实际上只在 CA 中观察到它应该工作,除了当我将它更改为给我 2010 块组地理位置时,它会中断:
ca <- tidycensus::get_decennial(state = "CA", geography = "block group",
variables = "B00001_001", geometry = TRUE,
year = 2010)
理想情况下,我想找到/编写一个函数,允许我输入我的数据框的名称以及其中包含我的纬度和经度数据的列,然后添加一个带有FIPS 代码(在块组级别,来自 2010 年人口普查) 或者,我可以上传一个 .csv 并返回一个 .csv 的地方会很棒。或者一个 Python 包很容易被 Python 知识非常有限的人实现。等等等等等等。
示例数据框(用于 R):
testdata <- structure(list(unique_id = c(5392085L, 14789082L, 11023930L, 4005454L, 13701322L, 10821557L, 11397828L, 15709999L, 475895L, 1546307L), GE_LATITUDE_2010 = c(38.272084, 33.013099, 39.019289, 33.992753, 32.6104, 33.717793, 34.550265, 32.842897, 33.754883, 38.461337), GE_LONGITUDE_2010 = c(-122.644619, -117.05967, -121.006352, -118.26259, -117.057227, -118.044996, -117.277502, -116.890541, -116.983093, -121.389269)), row.names = c(NA, -10L), class = "data.frame")
【问题讨论】:
为什么你认为下载 shapefile 会低效?你试过了吗? 在加利福尼亚下载块组的 shapefile 可能需要一点时间,但远不及对 1600 万行进行地理编码。另外它是免费的。如果您可以比“tidycensus break”更具体,那将很有帮助;幸运的是,我使用人口普查数据,并且可以立即注意到这是一个 ACS 可变数字,您想要一个十年一次的数字。如果您实际上不需要人口普查数据,只需 shapefile,只需从 Census TIGER 网站下载(或使用tigris
,tidycensus
调用)
关于实际计算:根据您的坐标创建一个空间对象。我喜欢sf
。获取块组的 shapefile(来自人口普查局)并进行空间叠加。如果您不再需要空间数据,只需要 ID、坐标和 BG FIPS,则放弃其余部分
【参考方案1】:
如果我正确理解了您的问题,那么您有 lat 和 lon 数据,并且您想要与坐标关联的 FIPS 代码。
要使用 Python 做到这一点,您可以执行以下操作:
你的样本df:
unique_id=['5392085L', '14789082L', '11023930L', '4005454L', '13701322L', '10821557L',
'11397828L', '15709999L', '475895L', '1546307L']
GE_LATITUDE_2010=[38.272084, 33.013099, 39.019289, 33.992753, 32.6104, 33.717793,
34.550265, 32.842897, 33.754883, 38.461337]
GE_LONGITUDE_2010=[-122.644619, -117.05967, -121.006352, -118.26259, -117.057227,
-118.044996, -117.277502, -116.890541, -116.983093, -121.389269]
df=pd.DataFrame(columns=['unique_id','GE_LATITUDE_2010','GE_LONGITUDE_2010'])
def get_fips_num(df):
df_1=df[['GE_LONGITUDE_2010','GE_LATITUDE_2010','unique_id']]
fips_lst=[]
unique_id=[]
for i,e,o in df_1.itertuples(index=False):
try:
lo=i
la=e
ven=o
link="https://geo.fcc.gov/api/census/area?lat="+str(la)+"&lon="+str(lo)+"&format=json"
with urllib.request.urlopen(link) as url:
data = json.loads(url.read().decode())
fips_lst.append(data['results'][0]['block_fips'])
unique_id.append(ven)
except (RuntimeError, TypeError, NameError,IndexError):
pass
df1=pd.DataFrame(columns=['fips','unique_id'],index=range(len(fips_lst)))
for a in range(len(fips_lst)):
df1.loc[a].fips = fips_lst[a]
df1.loc[a].unique_id = unique_id[a]
df1['fips']=df1['fips'].str[:11]
return df1
当您在 df 上运行代码时,您应该得到以下 df:
get_fips_num(df)
enter image description here
【讨论】:
以上是关于从 1600 万+ lat/long 获取 FIPS 块代码的主要内容,如果未能解决你的问题,请参考以下文章
Blob 存储上的 Azure 触发器,从图像 (Blob) 中提取 EXIF (lat/long/direction...) 数据
如何在 Google Map iOS Swift 中获取点击位置的 Lat Long
从浮点 lat long 创建的 CLLocation 显示更高的精度