Pandas - 使用 itertuples 创建列

Posted

技术标签:

【中文标题】Pandas - 使用 itertuples 创建列【英文标题】:Pandas - Create column using itertuples 【发布时间】:2017-11-19 12:01:40 【问题描述】:

我有一个pandas.DataFrameAcctIdLatitudeLongitude。我也有一个坐标列表。我正在尝试计算纬度和经度与列表中每个坐标对之间的距离(使用半正弦公式)。然后我想返回最小距离,并在数据框中创建一个带有值的新列。

但是,我的输出表只返回循环中最后一行的距离值。我尝试过使用itertuplesiterrows 和普通循环,但这些方法都不适合我。

df
AcctId   Latitude   Longitude
123      40.50      -90.13
123      40.53      -90.21
123      40.56      -90.45
123      40.63      -91.34

coords = [41.45,-95.13,39.53,-100.42,45.53,-95.32]

for row in df.itertuples():
    Latitude = row[1]
    Longitude = row[2]
    distances = []
    lat = []
    lng = []
    for i in xrange(0, len(coords),2):
          distances.append(haversine_formula(Latitude,coords[i],Longitude,coords[i+1])
          lat.append(coords[i])
          lng.append(coords[i+1])
          min_distance = min(distances)
    df['Output'] = min_distance

期望的输出:

df
AcctId   Latitude    Longitude    Output
123      40.50      -90.13         23.21
123      40.53      -90.21         38.42
123      40.56      -90.45         41.49
123      40.63      -91.34         42.45

实际输出:

df
AcctId   Latitude    Longitude    Output
123      40.50      -90.13         42.45
123      40.53      -90.21         42.45
123      40.56      -90.45         42.45
123      40.63      -91.34         42.45

最终代码

for row in df.itertuples():
    def min_distance(row):
        here = (row.Latitude, row.Longitude)
        return min(haversine(here, coord) for coord in coords)
    df['Nearest_Distance'] = df.apply(min_distance, axis=1)

【问题讨论】:

【参考方案1】:

您正在寻找pandas.DataFrame.apply()。比如:

代码:

df['output'] = df.apply(min_distance, axis=1)

测试代码:

df = pd.read_fwf(StringIO(u'''
        AcctId   Latitude   Longitude
        123      40.50      -90.13
        123      40.53      -90.21
        123      40.56      -90.45
        123      40.63      -91.34'''), header=1)

coords = [
    (41.45, -95.13),
    (39.53, -100.42),
    (45.53, -95.32)
]

from haversine import haversine

def min_distance(row):
    here = (row.Latitude, row.Longitude)
    return min(haversine(here, coord) for coord in coords)

df['output'] = df.apply(min_distance, axis=1)

print(df)

结果:

   AcctId  Latitude  Longitude      output
0     123     40.50     -90.13  432.775598
1     123     40.53     -90.21  425.363959
2     123     40.56     -90.45  404.934516
3     123     40.63     -91.34  330.649766

【讨论】:

太棒了。我在这方面工作太久了。感谢您的帮助! 此解决方案有效,但在应用于大型数据帧(>2MM 行)时,df.apply 运行速度非常慢。对于df.apply 的替代方案有什么建议吗? 我敢打赌,主要缺乏速度是在haversine计算中。您应该分析代码。如果我是对的,您可能会考虑对距离进行估计,只需要对点的子集进行半正弦运算。 估计距离的好方法是什么?原谅我的无知——我对 Python 还很陌生。 好吧,如果您在某个纬度以下,您可以简单地使用sqrt(d_lat**2 + d_long**2) 进行初步近似,这样您就可以找到附近的东西。甚至更简单的是min(d_lat, d_long) 可以在候选人附近找到。将真正取决于您的数据的性质。

以上是关于Pandas - 使用 itertuples 创建列的主要内容,如果未能解决你的问题,请参考以下文章

ValueError:在 Pandas 数据帧上使用 itertuples() 时解包的值太多

pandas遍历dataframe的行:迭代遍历dataframe的数据行iterrows函数itertuple函数

Pandas df.itertuples 在打印时重命名数据框列

pandas使用itertuples函数迭代dataframe中的数据行并自定义修改行中的数值(update row while iterating over the rows)

Pandas中DataFrame的学习笔记~

Pandas中DataFrame的学习笔记~