You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Python读取xyz转shapefile报must be real number not str错

问题原因

报错must be real number, not str的直接原因是构造shapely的Point对象时传入了字符串类型值,不符合坐标必须为数值的要求,根因是代码的文件读取逻辑存在几个明确问题:

  • 分隔符配置不匹配:你提供的xyz样例使用空格作为列分隔符,但代码中读取xyz/asc时的分隔符规则sep=r'\,|\t'仅匹配逗号和制表符,完全没有覆盖空格场景,pandas无法将每行正确拆分为x、y、z三个独立列,要么整行内容作为字符串存入第一列,要么拆分后列值保留字符串类型,传入Point时直接触发类型错误。
  • 硬编码跳行逻辑错误:你给出的xyz文件全为数值数据,不存在前置表头/说明行,代码中写死的skiprows=2会直接跳过前两行有效坐标,属于冗余bug,虽不触发本次报错,但会造成数据丢失。
  • 额外兼容隐患:代码用os.path.basename(xyz_path)[:-4]提取输出文件名,硬编码切片长度仅适配3位长度的扩展名,遇到.text这类4位扩展名的文件会把文件名切坏;读取文件时未显式指定列类型,遇到异常值时pandas可能自动将列识别为字符串类型,触发同类报错。
修复方法
  1. 将分隔符统一改为r'\s+',可匹配任意数量的空格、制表符、连续空白,覆盖所有常见的坐标文本文件分隔场景。
  2. 移除硬编码的skiprows=2,如果部分文件确实带2行前置说明,单独加判断逻辑,不要全局生效。
  3. 读取文件时显式指定x/y/z三列为float类型,避免pandas自动识别类型出错。
  4. 用os.path.splitext替换硬编码切片的文件名提取逻辑,兼容任意长度的扩展名。
  5. 读取后过滤空值行,避免缺失值传入Point构造函数。

修复后的核心代码段如下:

try:
    xyz_path = self.jobDict['xyz_key'][0]

    print(f'{datetime.now()} get_object (start)')
    input_file = self.s3_client.get_object(Bucket=self.jobDict['bucket'], Key=xyz_path)
    print(f'{datetime.now()} get_object (end) : {xyz_path}')

    file_extension = os.path.splitext(xyz_path)[-1].lower()
    # 安全提取无扩展名的文件名
    output_file = os.path.splitext(os.path.basename(xyz_path))[0]
    file_content = io.BytesIO(input_file['Body'].read())

    if file_extension in ("xyz", "asc"):
        df = pd.read_table(
            file_content,
            sep=r'\s+',
            engine='python',
            names=['x', 'y', 'z'],
            dtype={'x': float, 'y': float, 'z': float}
        )
    elif file_extension in ("txt", "text", "csv"):
        df = pd.read_csv(
            file_content,
            sep=r'\s+',
            names=['x', 'y', 'z'],
            dtype={'x': float, 'y': float, 'z': float}
        )

    # 过滤含空值的无效数据行
    df = df.dropna(subset=['x', 'y', 'z'])
    gdf = gpd.GeoDataFrame(
        df,
        geometry=df.apply(lambda row: Point(row.x, row.y, row.z), axis=1),
        # 根据数据实际坐标系指定crs,避免后续空间处理出错
        crs="EPSG:326XX"
    )

    gdf.to_file(f"{output_file}.shp")
    shapefile = f"{output_file}.shp"
    print("Shapefile Created!")

注:如果业务场景中确实存在带2行表头的xyz/asc文件,不要直接写死skiprows=2,可以先读取文件前N行判断内容是否为数值,动态决定跳过行数,避免误删有效数据。

内容的提问来源于stack exchange,提问作者userhelp

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.27 08:57:21