เร่งการตรวจสอบตามลำดับหากจุดอยู่ในรูปร่างใน Python

ฉันมีรหัสตามลำดับว่าพิกัดคาร์ทีเซียนทุกคู่ที่พบใน DataFrame ของฉันอยู่ในพื้นที่ปิดล้อมทางเรขาคณิตหรือไม่ แต่ฉันสงสัยว่ามันค่อนข้างช้าเพราะมันไม่ได้เป็นแบบเวกเตอร์ นี่คือตัวอย่าง:

from matplotlib.patches import Rectangle

r1 = Rectangle((0,0), 10, 10)
r2 = Rectangle((50,50), 10, 10)

df = pd.DataFrame([[1,2],[-1,5], [51,52]], columns=['x', 'y'])

for j in range(df.shape[0]):
    coordinates = df.x.iloc[j], df.y.iloc[j]
    if r1.contains_point(coordinates):
        df['location'].iloc[j] = 0
    else r2.contains_point(coordinates):
        df['location'].iloc[j] = 1

ใครสามารถเสนอแนวทางเร่งความเร็วได้บ้าง?


person splinter    schedule 22.03.2017    source แหล่งที่มา


คำตอบ (1)


เป็นการดีกว่าที่จะแปลงแพตช์สี่เหลี่ยมเป็นอาร์เรย์และดำเนินการแก้ไขหลังจากอนุมานขอบเขตที่แพตช์เหล่านั้นถูกกระจายออกไป

def seqcheck_vect(df):
    xy = df[["x", "y"]].values
    e1 = np.asarray(rec1.get_extents())
    e2 = np.asarray(rec2.get_extents())
    r1m1, r1m2 = np.min(e1), np.max(e1)
    r2m1, r2m2 = np.min(e2), np.max(e2)
    out = np.where(((xy >= r1m1) & (xy <= r1m2)).all(axis=1), 0, 
                   np.where(((xy >= r2m1) & (xy <= r2m2)).all(axis=1), 1, np.nan))
    return df.assign(location=out)

สำหรับตัวอย่างที่กำหนด ฟังก์ชันจะส่งออก:

ป้อนคำอธิบายรูปภาพที่นี่


เกณฑ์มาตรฐาน:

def loopy_version(df):
    for j in range(df.shape[0]):
        coordinates = df.x.iloc[j], df.y.iloc[j]
        if rec1.contains_point(coordinates):
            df.loc[j, "location"] = 0
        elif rec2.contains_point(coordinates):
            df.loc[j, "location"] = 1
        else:
            pass
    return df

ทดสอบบน DF จาก 10,000 แถว:

np.random.seed(42)
df  = pd.DataFrame(np.random.randint(0, 100, (10000,2)), columns=list("xy"))

# check if both give same outcome
loopy_version(df).equals(seqcheck_vect(df))
True

%timeit loopy_version(df)
1 loop, best of 3: 3.8 s per loop

%timeit seqcheck_vect(df)
1000 loops, best of 3: 1.73 ms per loop

ดังนั้นแนวทางเวคเตอร์จึงเร็วกว่าประมาณ 2,200 เท่าเมื่อเทียบกับวิธีแบบวนซ้ำ

person Nickil Maveli    schedule 22.03.2017
comment
ขอบคุณ ฉันสงสัยว่ามีวิธีการทั่วไปที่ไม่ต้องใช้เป็นรูปสี่เหลี่ยมผืนผ้า แต่เป็นแบบเวกเตอร์หรือไม่ แนวทางของคุณขึ้นอยู่กับมันถ้าฉันจำไม่ผิด - person splinter; 22.03.2017
comment
โดยพื้นฐานแล้วโครงสร้างใดๆ ที่มีช่วงเพื่อเปรียบเทียบกับค่าที่มีอยู่ใน DF จะเป็นไปตามการใช้งานที่คล้ายกันดังที่แสดงไว้ด้านบน ควรมีวิธีที่คุณสามารถแยกจุดเริ่มต้นและจุดสิ้นสุดออกมาและเก็บผลลัพธ์ไว้ในอาร์เรย์ - person Nickil Maveli; 22.03.2017
comment
นอกจากนี้ แพตช์ทั้งหมดยังมีเมธอด .get_extents() ดังนั้นฉันเดาว่าไม่น่าจะมีปัญหาอะไร - person Nickil Maveli; 22.03.2017