【问题标题】:Pandas - Go through 2 columns (latitude and longitude) and find the distance between each coordinate and a specific placePandas - 遍历 2 列(纬度和经度)并找到每个坐标与特定地点之间的距离
【发布时间】:2018-07-19 14:22:52
【问题描述】:

我有一个包含 3 列的数据框(称为坐标):索引、纬度、经度 - 它大约有 1,000 行。我有一个特定地点的坐标,并想找到该地点与数据框中所有坐标之间的距离。目前,我可以使用 geopy.distance 来查找两个特定坐标之间的距离。例如

import geopy.distance
site_coords = (38.898556, -77.037852)
place2_coords = (38.897147, -77.043934)
print(geopy.distance.vincenty(site_coords, place2_coords).km)

上面的代码给出了0.5503161689006362(我已经检查过,这是正确的)

我的问题是循环遍历数据框(称为坐标)并计算该数据框中所有坐标的距离。目前,这就是我所拥有的:

import geopy.distance
import pandas as pd
df = pd.read_csv('coordinates.csv', sep=',', header=None)

site_coords = (38.898556, -77.037852)
for index, row in df.iterrows():
    place2_coords = df
    x = geopy.distance.vincenty(site_coords, place2_coords).km
    print(x)

但是,当我打印 x 时,它多次打印相同的距离并且距离不正确。坐标文件看起来像(在记事本中打开时) - 但有更多行:

,Latitude,Longitude
0,73.3645,-0.9015
1,73.3645,-0.3995
2,73.3645,-0.5825

所以我需要一种方法来循环并找到距离。

【问题讨论】:

  • 您的循环正在计算在循环外定义的site_coords 和在某处定义但绝对不在循环内的tile_coords 之间的距离。所以你的循环只是一遍又一遍地计算同样的事情。您的意思是在 x 的计算中使用 place2_coords 吗?
  • 是的,抱歉,tile_coords 是 place2_coords。是的,所以我需要 place2_coords 更改并成为坐标文件@ALollz 中的所有值
  • 根据文档geopy.readthedocs.io/en/stable/…vincenty 已被弃用,你知道吗?
  • 哦,我不是我会改变的,谢谢@Yuca。但我仍然需要找到一种方法来遍历整个坐标
  • 数据框的列是否只有“纬度”和“经度”?

标签: python pandas


【解决方案1】:

在此处查看sechilds 的变体。 site_coords 是 def 的输入。 apply 函数现在使用 2 个参数:来自 DataFrame 的 rowsite_coords

import pandas as pd
import numpy as np
import geopy.distance

def calc_distance(row, site_coords):
    station_coords = (row['lat'], row['lon'])
    d = geopy.distance.distance(site_coords, station_coords).km
    return(d)

df['distance'] = df.apply(calc_distance, site_coords=(38.898556, -77.037852), axis=1)

【讨论】:

    【解决方案2】:

    如果你的文件看起来像

    ,Latitude,Longitude
    0,73.3645,-0.9015
    1,73.3645,-0.3995
    2,73.3645,-0.5825
    

    但您阅读时使用“head=None”,

    df = pd.read_csv('coordinates.csv', sep=',', header=None)
    

    第一行将改为数据行。这可能是您收到“AttributeError: 'Series' object has no attribute 'Latitude'”的原因。

    尝试从您的代码中删除“header=None”。

    df = pd.read_csv(StringIO(s), sep=',')
    site_coords = (38.898556, -77.037852)
    
    df.apply(lambda row: geopy.distance.vincenty(site_coords, (row.Latitude, row.Longitude)).km, axis=1)
    

    【讨论】:

    • 是的,这就是问题,谢谢。应用是贯穿所有列的重要部分。还有 lambda 的目的是什么?
    • 没什么特别的。很抱歉造成混淆,我发布的代码正是我为测试而输入的——我想少输入。 sechilds 的答案肯定更好。
    • 这似乎是一个非常菜鸟的问题,但如果我输入 x = df.apply(lambda row ..... 中的第一项是否是我的第一个坐标?文件?
    • 是的,订单被保留。
    【解决方案3】:

    iterrows 方法将为数据框的每一行提供一个pandas.Series 对象,因此您可以稍微不同地创建place2_coords

    import geopy.distance
    import pandas as pd
    df = pd.read_csv('coordinates.csv', sep=',')
    
    site_coords = (38.898556, -77.037852)
    for index, row in df.iterrows():
        place2_coords = (row.Latitude, row.Longitude)
        x = geopy.distance.vincenty(site_coords, place2_coords )).km
        print(x)
    

    对于 pandas,不推荐使用循环行的方法。相反,您可以沿列应用函数。

    def calc_distance(x):
        site_coords = (38.898556, -77.037852)
        place2_coords = (x.Latitude, x.Longitude)
        return geopy.distance.vincenty(site_coords, place2_coords )).km
    df.apply(calc_distance, axis = 1)
    

    【讨论】:

    • 当我运行 iterrows 方法时,我收到此错误 AttributeError: 'Series' object has no attribute 'Latitude'。同样在第二种方法中,您将 x 传递给函数这是数据帧吗?
    • 我也收到其他方法的相同错误
    • 错误是因为读取csv文件时的header=None。我将对其进行编辑。
    【解决方案4】:

    有几件事,首先您要询问元组和数据框之间的距离,我不确定它是如何工作的。但是,假设数据框 df 只有两列,以下循环应该适合您

    site_coords = (38.898556, -77.037852)
    for index, row in df.iterrows():
        if index > 0:
            x = geopy.distance.vincenty(site_coords, (row[1],row[2])).km
            print(x)
    

    【讨论】:

    • 我收到此错误:ValueError: cannot index with vector contains NA / NaN values。数据框确实包含 3 行,唯一的方法是尝试删除第一行,因为不需要第一行,
    • 第一行是 nans 吗?因为我没有数据,所以我无法复制您的具体条件,听起来您的 csv 在某处有一个空行
    • 不,我的数据不应该有任何 Nans,第一行只是填充了越来越多的数字,这些数字根本没有用。你知道我怎样才能删除这个专栏并再次尝试运行你的代码吗?
    • 这次我得到了一个不同的错误——ValueError:基于位置的索引只能有 [integer, integer slice (START point is INCLUDED, END point is EXCLUDED), listlike of integers, boolean array] 类型。
    • TypeError: '>' 在 'str' 和 'int' 的实例之间不支持
    猜你喜欢
    • 2017-11-05
    • 2016-02-03
    • 1970-01-01
    • 2018-04-01
    • 2015-04-20
    • 2011-09-16
    相关资源
    最近更新 更多