Python:如何正确使用apply()?

时间:2019-06-13 13:29:54

标签: python pandas apply geopandas

我有一个包含点的geopandas数据框

df:

        geometry
    0   POINT (806470.3646198167 2064879.919354021)
    1   POINT (792603.391127742 2170760.8355139)
    2   POINT (787263.3037740411 2050925.953643546)
    3   POINT (809203.6762813283 2160874.194588484)
    4   POINT (781668.2687635225 2051524.634389534)

对于每个要应用此功能的点:

def returnValuePoints(df, i):
    points_list = [ (df['geometry'][i].x, df['geometry'][i].y) ] #list of X,Y coordinates
    for point in points_list:
        col = int((point[0] - xOrigin) / pixelWidth)
        row = int((yOrigin - point[1] ) / pixelHeight)
        return (row, col)

这就是我在做什么:

for i in df.index:
    val = returnValuePoints(df, data, i)

如何避免循环,并使用apply()将此功能应用于所有行

3 个答案:

答案 0 :(得分:1)

关于以下代码的警告:由于无法访问geopandas环境,因此我尚未进行实际测试。但是,我认为它应该可以工作。

我认为您实际上不想在这里使用申请。使用geopandas方法,可以通过应用一些仿射变换来获得点的geopandas GeoSeries: 首先,您用translate xOrigin, yOrigin点系列:

translated = df['geometry'].translate(xoff=-1*xOrigin, yoff=-1*yOrigin)

然后,您既可以围绕x轴进行反射,也可以使用pixelWidth, pixelHeight通过scale进行缩放:

scaled_translated = translated.scale(xfact=1/pixelWidth, yfact=-1/pixelHeight)

在此处乘以-1即可进行反射。相反,如果您打算做(point[1] - yOrigin),则可以用1代替-1。

这将给您GeoSeries。如果需要一系列 integer 点对,则必须做更多的工作。下面的代码将为您提供两个分别带有x和y值的整数Series(要求geopandas版本> 0.3.0):

x_val = scaled_translated.x.astype(int)
y_val = scaled_translated.y.astype(int)

然后,您可以将其放入原始数据框中:

df['x_val'] = x_val
df['y_val'] = y_val

如果您真的想要一个元组列表(我想您可能不应该!您失去了熊猫的所有优势!),您可以这样做:

list(df[['x_val', 'y_val']].itertuples(index=False, name=None))

答案 1 :(得分:0)

首先,您需要重组您的方法,以便它采用可在apply中使用lambda函数传递的值(考虑如何对单个行的值进行操作):

def returnValuePoints(x, y):
    point = (x, y)
    col = int((point[0] - xOrigin) / pixelWidth)
    row = int((yOrigin - point[1] ) / pixelHeight)
    return (row, col)

第二,您可以使用axis = 1调用数据框上的Apply,以便能够访问每一行的列值:

val = df.apply(lambda x: returnValuePoints(x.geometry.x, x.geometry.y), axis=1)

答案 2 :(得分:0)

我将向您展示一个示例。

import pandas as pd 

# reading csv 
s = pd.read_csv("stock.csv", squeeze = True) 

# defining function to check price 
def fun(num): 

    if num<200: 
        return "Low"

    elif num>= 200 and num<400: 
        return "Normal"

    else: 
        return "High"

# passing function to apply and storing returned series in new 
new = s.apply(fun) 

# printing first 3 element 
print(new.head(3)) 

# printing elements somewhere near the middle of series 
print(new[1400], new[1500], new[1600]) 

# printing last 3 elements 
print(new.tail(3)) 

Here is the output