【问题标题】:Splitting a mixed number string from a dataframe column and converting it to a float从数据框列中拆分混合数字字符串并将其转换为浮点数
【发布时间】:2016-09-29 01:14:58
【问题描述】:

我有一个数据框,其中有一列字符串是整数和带分数的混合。我想将列 'y' 转换为浮点数。

x            y         z
0            4      Info
1        8 1/2      Info
2          3/4      Info
3           10      Info
4            4      Info
5        6 1/4      Info

我正在考虑的逻辑是将列 'y' 拆分为 ' ' 和 '/' 以创建三个看起来像这样的单独列。

x         base        b        c         z
0            4        0        0      Info
1            8        1        2      Info
2            0        3        4      Info
3           10        0        0      Info
4            4        0        0      Info
5            6        1        4      Info

从这里我可以

def convertReplace(df):
    convert = lambda x: float(x)
    df['base'].apply(convert)
    df['b'].apply(convert)
    df['c'].apply(convert)
    decimal = lambda x,y: x/y        
    try:
        df['d'] = decimal(df['b'],df['c'])
        df['y'] = df['base'] + df['d']
    except:
        df['y'] = df['base']
    return df

这可能有效,但我无法使用 here 找到的方法拆分列。

df = pd.DataFrame(df.y.str.split(' ',1).str.split('/',1).tolist(),columns = ['base','b','c'])

错误表示每次可能是 1、2 或 3 时它需要 3 个参数。即使 this thread 也不使用多个分隔符。

实际的数据框有超过 40 万行。效率会很好,但我对完成它更感兴趣。这个逻辑是正确的还是有更简洁的方法来做到这一点?任何帮助表示赞赏。

【问题讨论】:

    标签: python pandas split fractions


    【解决方案1】:

    你可以试试fractions 模块。这是一个单行:

    import fractions
    df['y_float'] = df['y'].apply(lambda frac: float(sum([fractions.Fraction(x) for x in frac.split()])))
    

    这给出了:

           y     z  y_float
    0      4  Info     4.00
    1  8 1/2  Info     8.50
    2    3/4  Info     0.75
    3     10  Info    10.00
    4      4  Info     4.00
    5  6 1/4  Info     6.25
    

    [编辑] 更正了负分数以及无效文本的版本:

    我意识到上述方法不适用于负分数,所以这里考虑了这一点。事实证明,单行此将非常棘手!

    def get_sign(num_str):
        """
        Verify the sign of the fraction
        """
        return 1-2*num_str.startswith('-')
    
    def is_valid_fraction(text_str):
        """
        Check if the string provided is a valid fraction.
        Here I just used a quick example to check for something of the form of the fraction you have. For something more robust based on what your data can potentially contain, a regex approach would be better.
        """
        return text_str.replace(' ', '').replace('-', '').replace('/', '').isdigit()
    
    def convert_to_float(text_str):
        """
        Convert an incoming string to a float if it is a fraction
        """
         if is_valid_fraction(text_str):
             sgn = get_sign(text_str)
             return sgn*float(sum([abs(fractions.Fraction(x)) for x in text_str.split()]))
         else:
             return pd.np.nan # Insert a NaN if it is invalid text
    

    所以现在你将拥有这个:

    >>> df['y_float'] = df['y'].apply(lambda frac: convert_to_float(frac))
    >>> df
                  y     z  y_float
    0             4  Info     4.00
    1         8 1/2  Info     8.50
    2           3/4  Info     0.75
    3            10  Info    10.00
    4             0  Info     0.00
    5         6 1/4  Info     6.25
    6        -3 2/5  Info    -3.40
    7          -4/5  Info    -0.80
    8  gibberish100  Info      NaN
    

    【讨论】:

    • 我认为这可能有效,但我的实际数据有点混乱。一些值包括文本。我如何应用它但跳过分数模块遇到的无效文字?是否有用于格式检查的 if-else 检查?在这种情况下你会使用“loc”命令吗?
    • 更新了解决负分数和模糊文本的解决方案
    • 太棒了!这真的很有帮助。谢谢@vk1011!
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2019-07-06
    • 2011-11-25
    • 1970-01-01
    • 2019-02-02
    • 1970-01-01
    • 2018-11-30
    相关资源
    最近更新 更多