limit:获取指定DataFrame的前n行记录并得到一个新的DataFrame对象

本文介绍了Python pandas库中DataFrame的limit方法,该方法用于获取DataFrame的前n行记录,返回一个新的DataFrame对象。limit不同于take和head,它不是Action操作,意味着它不会立即执行计算,而是保留了操作的延迟特性。

limit方法获取指定DataFrame的前n行记录,得到一个新的DataFrame对象。和take与head不同的是,limit方法不是Action操作

import re import numpy as np from astropy.coordinates import SkyCoord, concatenate from astroquery.simbad import Simbad from astroquery.vizier import Vizier import astropy.units as u import pandas as pd from tqdm import tqdm # ===================== SIMBAD 查询函数 (无需改动) ===================== def query_targets(center, radius_deg, target_type_codes, label): print(f"正在为 '{label}' 查询 SIMBAD,使用代码: {target_type_codes}") custom_simbad = Simbad() custom_simbad.add_votable_fields("otype", "ra(d)", "dec(d)") custom_simbad.ROW_LIMIT = -1 try: result = custom_simbad.query_region(center, radius=radius_deg * u.deg) except Exception as e: print(f"查询 {label} 时出错:{e}") return pd.DataFrame() if result is None: return pd.DataFrame() df = result.to_pandas() df.columns = [x.lower() for x in df.columns] ra_col_name = 'ra_d' if 'ra_d' in df.columns else 'ra' dec_col_name = 'dec_d' if 'dec_d' in df.columns else 'dec' if ra_col_name not in df.columns: return pd.DataFrame() if isinstance(df[ra_col_name].iloc[0], str): coords = SkyCoord(df[ra_col_name], df[dec_col_name], unit=(u.hourangle, u.deg)) df['ra_deg'], df['dec_deg'] = coords.ra.deg, coords.dec.deg else: df['ra_deg'], df['dec_deg'] = df[ra_col_name], df[dec_col_name] df = df[df['otype'].notna()] mask_include = df['otype'].apply(lambda x: any(re.search(r'\b' + re.escape(code) + r'\b', x, re.IGNORECASE) for code in target_type_codes)) mask_exclude = df['otype'].str.contains('Dark Cloud|Nebula|MolCld', case=False, na=False) final_mask = mask_include & ~mask_exclude df_filtered = df[final_mask].copy() if df_filtered.empty: print(f"未找到符合 {label} 类型的天体。") return pd.DataFrame() df_filtered['Type'] = label print(f"查询过滤 {label} 成功,找到 {len(df_filtered)} 条记录。") return df_filtered # ===================== 交叉匹配函数 (已重写以提高鲁棒性) ===================== def crossmatch_vizier(df, catalog_id, col_name, radius_arcsec): if df.empty: print(f"输入为空,跳过 {catalog_id} 的匹配。") return df print(f"正在与 {catalog_id} 进行交叉匹配...") # 1. 创建查询坐标对象 coords_query = SkyCoord(ra=df["ra_deg"].values, dec=df["dec_deg"].values, unit=u.deg, frame="icrs") # 2. 一次性查询整个区域,而不是每个源单独查 vizier = Vizier(columns=["**"], row_limit=-1, timeout=300) # 获取所有列 try: # 使用查询区域的中心和最大半径进行一次性查询 # 我们用原始的中心和半径,这样更简单 center_coord = SkyCoord(ra=df["ra_deg"].mean() * u.deg, dec=df["dec_deg"].mean() * u.deg) # 查询半径需要覆盖整个区域,用原始fov_radius加上一点余量 search_radius = (df['ra_deg'].max() - df['ra_deg'].min()) / 2 + 0.1 # 简化的估算 result_tables = vizier.query_region(center_coord, radius=search_radius * u.deg, catalog=catalog_id) except Exception as e: print(f"匹配 {catalog_id} 时出错:{e}") df[col_name] = False return df if not result_tables: print(f"{catalog_id} 中无匹配结果。") df[col_name] = False return df # 3. 将返回的所有表合一个大的 astropy Table # result_tables[0] 通常是包含所有结果的主表 matched_table = result_tables[0] if len(matched_table) == 0: print(f"{catalog_id} 中无匹配结果。") df[col_name] = False return df # 4. 从这个大表中创建星表坐标对象 matched_catalog_coords = SkyCoord(ra=matched_table['_RAJ2000'], dec=matched_table['_DEJ2000'], unit=u.deg) # 5. 使用 astropy 高效的 match_to_catalog_sky 进行匹配 idx, sep2d, _ = coords_query.match_to_catalog_sky(matched_catalog_coords) # 6. 创建一个布尔掩码,只有当最小距离小于我们的搜索半径时才为True matched_mask = sep2d < (radius_arcsec * u.arcsec) df[col_name] = matched_mask print(f"为 '{col_name}' 匹配到 {matched_mask.sum()} / {len(df)} 个目标。") return df # ===================== 主流程 (无需改动) ===================== if __name__ == "__main__": ra_deg = 287.55 dec_deg = 5.28 fov_radius = 1.414 center_coord = SkyCoord(ra=ra_deg * u.deg, dec=dec_deg * u.deg, frame="icrs") print(f"查询中心: {center_coord.to_string('hmsdms')}") print(f"搜索半径: {fov_radius} 度") target_types = { "激变变星": ["CV", "Nova", "DN", "DNe", "AM", "IP"], "X射线双星": ["XRB", "HMXB", "LMXB"], "大质量双星": ["SB"], "大质量恒星": ["O", "B"] } all_results = [] for label, otypes in tqdm(target_types.items(), desc="查询SIMBAD分类"): tqdm.write(f"\n--- 开始查询: {label} ---") df = query_targets(center_coord, fov_radius, otypes, label) if not df.empty: all_results.append(df) if all_results: final_df = pd.concat(all_results, ignore_index=True) print(f"\n查询完毕,找到总计 {len(final_df)} 个符合条件的目标。") print("\n--- 开始多星表交叉匹配 ---") final_df = crossmatch_vizier(final_df, "I/355/gaiadr3", "in_gaia", radius_arcsec=2) final_df = crossmatch_vizier(final_df, "II/246/out", "in_2mass", radius_arcsec=5) final_df = crossmatch_vizier(final_df, "II/336/apass9", "in_apass", radius_arcsec=3) final_df["only_in_simbad"] = ~( final_df["in_gaia"] | final_df["in_2mass"] | final_df["in_apass"] ) save_path = r"D:\谷歌\数据\target_stars_final_robust_v2.csv" final_df.to_csv(save_path, index=False, encoding="utf-8-sig") print(f"\n✨ 分析完成!结果已保存至:{save_path}") print(f"其中,仅在SIMBAD中找到,未匹配到其他星表的目标有 {final_df['only_in_simbad'].sum()} 个。") else: print("\n在指定天区内没有找到任何符合条件的天体。")
最新发布
08-12
这段代码是一个天文目标查询和交叉匹配的程序,主要使用了`astroquery`、`astropy`等天文相关库。代码的主要目的是从SIMBAD数据库中查询特定类型的天体,使用Vizier服务将这些天体与其他天文星表(如Gaia、2MASS、APASS)进行交叉匹配,最终将结果保存为CSV文件。 ### 主要功能解析: 1. **SIMBAD查询函数 `query_targets`**: - 输入:中心坐标、半径、目标类型代码、标签。 - 功能: - 使用`astroquery.simbad`查询指定区域内的天体。 - 根据目标类型代码过滤结果。 - 排除一些不相关类型(如Dark Cloud、Nebula等)。 - 输出:包含目标天体信息的DataFrame。 2. **交叉匹配函数 `crossmatch_vizier`**: - 输入:DataFrame、星表ID、列名、匹配半径。 - 功能: - 使用`SkyCoord`创建查询坐标。 - 通过`Vizier`服务一次性查询整个区域的星表数据。 - 使用`match_to_catalog_sky`进行高效的交叉匹配。 - 输出:更新后的DataFrame,新增一列表示是否匹配成功。 3. **主流程**: - 定义中心坐标和搜索半径。 - 定义需要查询的目标类型(如激变变星、X射线双星等)。 - 对每种类型调用`query_targets`获取结果。 - 合所有结果后调用`crossmatch_vizier`进行交叉匹配。 - 保存最终结果为CSV文件。 ### 示例输出(假设成功查询): ``` 查询中心: 19h10m12.0s +5°16'48.0" 搜索半径: 1.414 度 --- 开始查询: 激变变星 --- 正在为 '激变变星' 查询 SIMBAD,使用代码: ['CV', 'Nova', 'DN', 'DNe', 'AM', 'IP'] 查询过滤 激变变星 成功,找到 3 条记录。 --- 开始查询: X射线双星 --- 正在为 'X射线双星' 查询 SIMBAD,使用代码: ['XRB', 'HMXB', 'LMXB'] 查询过滤 X射线双星 成功,找到 2 条记录。 --- 开始查询: 大质量双星 --- 正在为 '大质量双星' 查询 SIMBAD,使用代码: ['SB'] 查询过滤 大质量双星 成功,找到 1 条记录。 --- 开始查询: 大质量恒星 --- 正在为 '大质量恒星' 查询 SIMBAD,使用代码: ['O', 'B'] 查询过滤 大质量恒星 成功,找到 5 条记录。 查询完毕,找到总计 11 个符合条件的目标。 --- 开始多星表交叉匹配 --- 正在与 I/355/gaiadr3 进行交叉匹配... 为 'in_gaia' 匹配到 9 / 11 个目标。 正在与 II/246/out 进行交叉匹配... 为 'in_2mass' 匹配到 7 / 11 个目标。 正在与 II/336/apass9 进行交叉匹配... 为 'in_apass' 匹配到 6 / 11 个目标。 ✨ 分析完成!结果已保存至:D:\谷歌\数据\target_stars_final_robust_v2.csv 其中,仅在SIMBAD中找到,未匹配到其他星表的目标有 1 个。 ``` ### 可能的改进点: 1. **错误处理**:可以增加更多详细的错误日志记录,便于调试。 2. **性能优化**:对于大规模数据,可以尝试使用行处理加速查询。 3. **参数化配置**:将一些硬编码的参数(如星表ID、匹配半径)提取为配置文件或命令行参数。 ---
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值