boostcampaitech7 / level2-competitiveds-recsys-06

level2-competitiveds-recsys-06 created by GitHub Classroom
2 stars 0 forks source link

[EDA] subway data set EDA #3

Closed ChoonB closed 3 weeks ago

ChoonB commented 1 month ago

할당: @ChoonB 기본 subway 관련 가설

---------추가 가설

ChoonB commented 1 month ago

1km내에 지하철역 찾는 코드를 아래와 같은 함수로 짰는데 시간이 너무 오래걸려서 다른 방식을 써보려 한다.

def find_subways_within_1km(row, subway_sorted):
    subways_within_1km = []
    for _, subway in subway_sorted.iterrows():
        distance = geodesic((row['latitude'], row['longitude']), (subway['latitude'], subway['longitude'])).meters
        if distance <= 1000:
            subways_within_1km.append(subway['subway_code'])
        elif distance > 1000 and len(subways_within_1km) > 0:
            break
    return len(subways_within_1km), subways_within_1km
xenx96 commented 1 month ago
from geopy.distance import geodesic
from typing import List
from tqdm import tqdm

subway = pd.read_csv(os.path.join(BASE_PATH, "subwayinfo.csv"))
train_data["lon_lat"] = train_data["longitude"].astype(str) + "-" + train_data["latitude"].astype(str)
train_data["lon_lat"] = train_data["lon_lat"].map(lambda x: x.split("-"))

subway["lon_lat"] = subway["longitude"].astype(str) + "-" + subway["latitude"].astype(str)
subway["lon_lat"] = subway["lon_lat"].map(lambda x: x.split("-"))
subway.head()
tqdm.pandas()
i = 0

def find_subways_within_1km(row) -> List[int]:
    subway["result"] = subway["lon_lat"].map(
        lambda x: True if geodesic((row[1], row[0]), (x[1], x[0])).meters <= 1000 else False)
    sb = subway.loc[subway["result"] == True,].index.values.tolist()
    subway.drop(columns=["result"], inplace=True)

    return sb

train_sb_df = train_data[["apt_idx", "latitude", "longitude"]].drop_duplicates()
train_sb_df["lon_lat"] = train_sb_df["longitude"].astype(str) + "-" + train_sb_df["latitude"].astype(str)
train_sb_df["lon_lat"] = train_sb_df["lon_lat"].map(lambda x: x.split("-"))
result = train_sb_df["lon_lat"].progress_map(find_subways_within_1km)
ChoonB commented 1 month ago
from sklearn.neighbors import BallTree

# 지구의 평균 반경 (킬로미터 단위)
EARTH_RADIUS_KM = 6371.0

# 아파트의 위도와 경도를 라디안으로 변환
temp_df_rad = np.radians(temp_df[['latitude', 'longitude']].values)

# 지하철 역의 위도와 경도를 라디안으로 변환
subway_sorted_rad = np.radians(subway_sorted[['latitude', 'longitude']].values)

# BallTree 생성 (Haversine 거리 메트릭 사용)
tree = BallTree(subway_sorted_rad, metric='haversine')

# 반경 1km을 라디안으로 변환
radius = 1 / EARTH_RADIUS_KM  # 약 0.000157 라디안

# 가장 가까운 지하철역과 거리 찾기
distances, indices = tree.query(temp_df_rad, k=1)
temp_df['nearest_subway_distance'] = distances.flatten() * EARTH_RADIUS_KM * 1000  # meters
temp_df['nearest_subway_idx'] = subway_sorted['subway_idx'].iloc[indices.flatten()].values

# 반경 1km 내의 지하철역 인덱스 찾기
indices_within_1km = tree.query_radius(temp_df_rad, r=radius)

# 반경 1km 내의 지하철역 개수
temp_df['num_subway_within_1km'] = [len(ind) for ind in indices_within_1km]

# 반경 1km 내의 지하철역 subway_idx 리스트
temp_df['list_subway_idx_within_1km'] = [subway_sorted['subway_idx'].iloc[ind].tolist() for ind in indices_within_1km]

# 반경 1km 내의 Interchange_station이 2 이상인 지하철역 존재 여부
interchange_counts = [subway_sorted['Interchange_station'].iloc[ind].ge(2).sum() for ind in indices_within_1km]
temp_df['has_Interchange_2_or_more'] = [count >= 1 for count in interchange_counts]

# 결과 확인
print(temp_df[['nearest_subway_idx', 'nearest_subway_distance', 'num_subway_within_1km', 
              'list_subway_idx_within_1km', 'has_Interchange_2_or_more']].head())