算法

时间:2016-10-18 02:44:10

标签: python pandas

我有一个这样的数据框:

df = pd.DataFrame({
    'A': ['a', 'a', 'a', 'a', 'a'],
    'lon1': [128.0, 135.0, 125.0, 123.0, 136.0],
    'lon2': [128.0, 135.0, 139.0, 142.0, 121.0],
    'lat1': [38.0, 32.0, 38.0, 38.0, 38.0],
    'lat2': [31.0, 32.0, 35.0, 38.0, 29.0],
    'angle': [0, 0, 0, 0, 0]
})

我想通过此函数计算每一行的角度并保存回角度列

def angle(lon1,lat1,lon2,lat2):
    dx = lon2 - lon1
    dy = lat2 - lat1
    direction = 0;
    if ((dx == 0) & (dy == 0)):  # same position
    return direction
    if (dx > 0.0) :    
        direction = 90-np.arctan2(dy,dx)*180/np.pi
    elif (dy > 0.0 ) :    
        direction = 180+(270-(np.arctan2(dy,dx)*180/np.pi))
    else :   
        direction = 360-(270+(np.arctan2(dy,dx)*180/np.pi))
        if (direction < 0) :
            direction += 360

    return (direction.astype(int) % 360)  

我试过

df.ix[df['A'].notnull(), 'angle'] =angle(
    df[df['A'].notnull()]['lon1'],
    df[df['A'].notnull()]['lat1'],
    df[df['A'].notnull()]['lon2'], 
    df[df['A'].notnull()]['lat2']) 

我收到了错误

  

ValueError:系列的真值是不明确的。使用a.empty,a.bool(),a.item(),a.any()或a.all()。

我试过for index,row in df.iterrows(): for循环的结果还可以,但是花了很长时间(原始数据大约是1000万行)

有人可以提供一些有效的方法吗?

2 个答案:

答案 0 :(得分:1)

您似乎正在尝试将函数angle(...)应用于数据框的每一行。

首先,有必要将所有字符串类型的数字转换为float,以便计算。

df1.loc[:, "lon1"] = df1.loc[:, "lon1"].astype("float")
df1.loc[:, "lon2"] = df1.loc[:, "lon2"].astype("float")
df1.loc[:, "lat1"] = df1.loc[:, "lat2"].astype("float")
df1.loc[:, "lat2"] = df1.loc[:, "lat2"].astype("float")

你去。

df1.loc[:, "angle"] = df1.apply(lambda x: angle(x["lon1"], x["lat1"], x["lon2"], x["lat2"]), axis = 1)

至于性能问题,这里有一些提示。

  1. 分析]。
  2. 使用numba进行JIT编译和函数的自动矢量化。

答案 1 :(得分:0)

我确定这是一个更具矢量化的解决方案,但这是一个使用apply方法的行方式版本的解决方案,它只会略微改变您的功能:

def angle(row):
    dx = row.lon2 - row.lon1
    dy = row.lat2 - row.lat1
    direction = 0;
    if ((dx == 0) & (dy == 0)):  # same position
        return direction
    if (dx > 0.0) :    
        direction = 90-np.arctan2(dy,dx)*180/np.pi
    elif (dy > 0.0 ) :    
        direction = 180+(270-(np.arctan2(dy,dx)*180/np.pi))
    else :   
        direction = 360-(270+(np.arctan2(dy,dx)*180/np.pi))
    if (direction < 0) :
        direction += 360

    return (direction.astype(int) % 360)  

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

输出:

    A   angle   lat1    lat2    lon1    lon2
0   a   180     38.0    31.0    128.0   128.0
1   a   0       32.0    32.0    135.0   135.0
2   a   102     38.0    35.0    125.0   139.0
3   a   90      38.0    38.0    123.0   142.0
4   a   239     38.0    29.0    136.0   121.0