【问题标题】:How do I extract mixed elements from a long list in pandas/ python如何从 pandas/python 的长列表中提取混合元素
【发布时间】:2021-04-15 18:58:03
【问题描述】:

我在需要清理的数据框中有以下长列表: df=pd.DataFrame({'点': ['Team A v Team Bn\n13 月 20:00 +147 st\nScoreO (1.5)\n1.142\nScoreU (1.5)\n5.50\nScoreO (2.5)\n1.48\ nScoreU (2.5)\n2.65\nScoreO (3.5)\n2.15\nScoreU (3.5)\n1.666\nScoreO (4.5)\n3.60\nScoreU (4.5)\n1. 285\nScoreO (5.5)\n6.50\nScoreU (5.5)\n1.10']})

df=pd.DataFrame({'Points':
['Team A v Team Bn\n13 Jan 20:00 +147 st\nScoreO (1.5)\n1.142\nScoreU (1.5)\n5.50\nScoreO (2.5)\n1.48\nScoreU (2.5)\n2.65\nScoreO (3.5)\n2.15\nScoreU (3.5)\n1.666\nScoreO (4.5)\n3.60\nScoreU (4.5)\n1.285\nScoreO (5.5)\n6.50\nScoreU (5.5)\n1.10']})

想要的结果:1.48\n2.65

因此,我想从列表中提取 ScoreO 和 ScoreU 的实际浮点分数 (2.5) 以实现上述目标。

我尝试过切片,但我离目标还很远,因此不会试图表现出我惨淡的失败(善良)。

【问题讨论】:

    标签: python-3.x regex pandas


    【解决方案1】:

    您可以尝试str.extractallScore(?:O|U) \(2\.5\)\n([0-9.]+),其中Score(?:O|U) \(2\.5\)\n 将匹配ScoreO (2.5)ScoreU (2.5) 加上一个新行,而([0-9.])+ 在下一行捕获分数:

    df.Points.str.extractall('Score(?:O|U) \(2\.5\)\n([0-9.]+)').unstack(level=1)
    
    #           0      
    # match     0     1
    # 0      1.48  2.65
    

    如果需要加入结果:

    df.Points.str.extractall('Score(?:O|U) \(2\.5\)\n([0-9.]+)')
      .groupby(level=0)
      .agg('\n'.join)
    
    #            0
    #0  1.48\n2.65
    

    【讨论】:

      【解决方案2】:

      首先,了解您的输入。你的实际字符串看起来像

      Team A v Team Bn
      13 Jan 20:00 +147 st
      ScoreO (1.5)
      1.142
      ScoreU (1.5)
      5.50
      ScoreO (2.5)
      1.48
      ScoreU (2.5)
      2.65
      ScoreO (3.5)
      2.15
      ScoreU (3.5)
      1.666
      ScoreO (4.5)
      3.60
      ScoreU (4.5)
      1.285
      ScoreO (5.5)
      6.50
      ScoreU (5.5)
      1.10
      

      现在,您想要获得一个 float 数值,该数值位于等于 ScoreO (2.5)ScoreU (2.5) 的行下方的行上。

      因此,您可以使用Score[OU] \(2\.5\)\n 或仅使用\(2\.5\)\n 设置上下文,因为这足以找到您需要开始匹配的上下文,然后您可以使用@987654327 @(你已经知道你需要的值是整行)或\d+\.\d+(因为你知道它是一个浮点值)。

      因此,您可以使用以下两种解决方案之一:

      >>> df['Points'].str.findall(r'Score[OU] \(2\.5\)\n(\d+\.\d+)').str.join('\n')
      0    1.48\n2.65
      >>> df['Points'].str.findall(r'\(2\.5\)\n(.+)').str.join('\n')
      0    1.48\n2.65
      

      regex demo

      【讨论】:

      • 感谢您的解决方案; 100% 以我喜欢的方式工作!选择了解决方案 2,因为我发现它很容易理解 :)
      【解决方案3】:

      在发布另一个解决方案时,我正在努力解决这个问题,但仍然有一些有用的东西。您可以将其转换为数据框,以便稍后选择其他分数(例如 3.5)

      >>> pat=r'ScoreO.+\((?P<ScoreO>\d+[.]\d+)\)\n(\d+[.]\d+)\nScoreU.+\((?P<ScoreU>\d+[.]\d+)\)\n(\d+[.]\d+)'
      >>> df = df.Points.str.extractall(pat).droplevel(1)
      >>> df.columns=['Score0','result1','ScoreU','result2']
      >>> df 
        Score0 result1 ScoreU result2
      0    1.5   1.142    1.5    5.50
      0    2.5    1.48    2.5    2.65
      0    3.5    2.15    3.5   1.666
      0    4.5    3.60    4.5   1.285
      0    5.5    6.50    5.5    1.10
      

      【讨论】:

        【解决方案4】:

        您可以将数据框转换为列表,按行拆分,然后遍历较小的字符串以查找您的数据:

        def findScores (df, search_term = "2.5"):
            lst = df.to_numpy().tolist() #converts df into list
            lst = lst[0][0].split("\n") #makes a list of strings
            result = ['ScoreO', 'ScoreU']
            for i in range(len(lst)):
                if lst[i] == f'ScoreO ({search_term})':
                    result[0] = lst[i+1]
                elif lst[i] == f'ScoreU ({search_term})':
                    result[1] = lst[i + 1]
            return result
        

        【讨论】:

        • 谢谢。会给出反馈,
        猜你喜欢
        • 2012-09-21
        • 2016-07-03
        • 1970-01-01
        • 2021-11-30
        • 2021-06-05
        • 2021-10-14
        • 2018-04-17
        • 2017-01-19
        • 2017-03-12
        相关资源
        最近更新 更多