Python 如何用对象中的子字符串替换值?

Python 如何用对象中的子字符串替换值?,python,pandas,dataframe,Python,Pandas,Dataframe,我有一个纬度数据集中的坐标,每个坐标以一个字母结尾(例如N) 仅检索数字并替换原始值的最佳方法是什么 我的尝试是: raw['LATITUDE'] = raw.loc[(raw['LATITUDE'].str.len() == 9)].str[0:8] 但我收到了一条AttributeError消息 AttributeError: 'DataFrame' object has no attribute 'str' 我还尝试用正则表达式替换这些值,但我不确定如何使其成功 谢谢你的建议 好的,让

我有一个纬度数据集中的坐标,每个坐标以一个字母结尾(例如N)

仅检索数字并替换原始值的最佳方法是什么

我的尝试是:

raw['LATITUDE'] = raw.loc[(raw['LATITUDE'].str.len() == 9)].str[0:8]
但我收到了一条AttributeError消息

AttributeError: 'DataFrame' object has no attribute 'str'
我还尝试用正则表达式替换这些值,但我不确定如何使其成功

谢谢你的建议


好的,让我们澄清两件事:

  • 您似乎正在使用混合数据类型。打印出原始['LATITUDE']
    apply(type).nunique()
    进行确认;它应该大于1

  • 您正在使用geodata。您的许多值都是无效的(0),我建议将其强制为NaN,因为这更能代表丢失的数据

  • 要解决您的问题,请尝试将所有内容保留到最后一个字符(
    :-1
    ):

    尽管您的列是混合数据类型,但这仍然有效,因为
    str
    访问器的设计目的是将非字符串行强制为NaN

    如果您希望保留0(我不推荐),请使用快速替换函数,如
    np.where

    raw['LATITUDE'] = np.where(
        raw.LATITUDE.eq(0), 0, raw['LATITUDE'].str[:-1].astype(float)
    )
    
    raw
       LATITUDE
    0   0.00000
    1  38.72496
    2  39.90272
    3  38.72927
    4  39.91152
    5  39.84841
    6   0.00000
    7   0.00000
    8   0.00000
    9  39.84941
    

    我不建议保留0s的原因是,从语义上讲,使用NaN来划分缺少的数据比使用0更有意义。

    在与dtype
    对象的系列中,似乎存在混合类型

    选项1

    您可以先尝试使用
    errors='concurve'
    转换为数值,然后在转换为
    float
    之前,使用所有字符填充NA

    s = pd.Series(['34.49881N', 0], dtype=object)
    
    s = pd.to_numeric(s, errors='coerce').fillna(s.str[:-1].astype(float))
    
    选项2

    你也可以反过来工作。这是不可取的,因为它不太严格,即您可能会在结果中发现意外类型

    s = s.str[:-1].astype(float).fillna(s)
    
    结果

    在这两种情况下,您都会发现:

    print(s)
    
    0    34.49881
    1     0.00000
    dtype: float64
    

    您可以使用
    where

    df.LATITUDE.where(df['LATITUDE'].str.len() == 9,df.LATITUDE.str[0:8])
    Out[956]: 
    0           0
    1    38.72496
    2    39.90272
    3    38.72927
    4    39.91152
    5    39.84841
    6           0
    7           0
    8           0
    9    39.84941
    Name: LATITUDE, dtype: object
    

    除非您确信您的数据始终只包含一个半球(无南半球纬度),否则我不建议使用子串方法,因为它会将(例如)39.2342N和39.2342S转换为相同的值

    相反,我将使用
    映射
    将字符串转换为一个带有反映半球的符号的数字:

    df['Fixed_Lat'] = df['LATITUDE'].map(lambda x: -float(x[:-1]) if x[-1] == 'S' else float(x[:-1]))
    

    这实际上是我的答案,但有不必要的漏洞。选项1做的事情比它需要的要多,选项2和我已经写的差不多,我不同意。使用
    s=pd.Series(['34.49881N',0],dtype=object)
    测试您的解决方案。混合对象列中的非字符串项被隐式转换为NaN,这简化了很多事情。我想OP只想要纬度,别的什么都不要。我建议从这些NAN开始。
    s.str[:-1].astype(float)
    可以工作,这就是真正需要工作的全部。我不明白你说的“不工作”是什么意思。。。如果你的意思是零消失了,那么是的,那些会变成南,他们应该知道,我不喜欢没有评论的否决票。我已经给你补偿了,祝你愉快。谢谢。你的解释直截了当、简单,而且奏效了。看完你的建议后,我宁愿把所有有争议的行都处理掉。你建议怎么做?@elbertkim你可以简单地按照
    raw=raw.dropna(subset=['LATITUDE'])
    的思路做一些事情。如果您想删除带有NaN的每一行,请选择
    raw=raw.dropna()
    。不客气:)
    df['Fixed_Lat'] = df['LATITUDE'].map(lambda x: -float(x[:-1]) if x[-1] == 'S' else float(x[:-1]))