【问题标题】:How to create columns from a string in a dataframe?如何从数据框中的字符串创建列?
【发布时间】:2021-08-18 13:01:33
【问题描述】:

我有什么:

import pandas as pd
inp = [{'long string':'ha: (tra: 1 la: 2) \n hi: (tra: 1 la: 2) \n ho: (tra: 1 la: 2)'}, 
{'long string':'hi: (tra: 1 la: 2) \n ha: (tra: 1 la: 2) \n ho: (tra: 1 la: 2)'}, 
{'long string':'ho: (tra: 1 la: 2) \n hi: (tra: 1 la: 2) \n ha: (tra: 1 la: 2)'}]
df = pd.DataFrame(inp)
df

给予

    long string
0   ha: (tra: 1 la: 2) \n hi: (tra: 1 la: 2) \n ho...
1   hi: (tra: 1 la: 2) \n ha: (tra: 1 la: 2) \n ho...
2   ho: (tra: 1 la: 2) \n hi: (tra: 1 la: 2) \n ha...

我想要什么

inp = {'ha-tra':['1', '1', '1'], 'ha-la':['2', '2', '2'], 'hi-tra':['1', '1', '1'], 'hi-la':['2', '2', '2'],'ho-tra':['1', '1', '1'], 'ho-la':['2', '2', '2']}
df = pd.DataFrame(inp)
df

给予

    ha-tra  ha-la   hi-tra  hi-la   ho-tra  ho-la
0   1       2       1       2       1       2
1   1       2       1       2       1       2
2   1       2       1       2       1       2

上下文

我想从一个大字符串中获取 (ha hi ho) 和 (tra la) 的每个组合,并从字符串中获取与这些组合相关的分数。问题是(ha hi ho)的顺序不一样。

【问题讨论】:

    标签: python regex pandas dataframe


    【解决方案1】:

    一种解决方法:

    df1 = (
        df['long string'].str.extractall(
            r'.*?([a-z]+)\s*?:\s*?\(([a-z]+):\s*(\d+)\s*([a-z]+):\s*(\d+)\)')
        .droplevel("match")
        .set_index(0, append=True)
    )
    
    d1 = df1.iloc[:, :2]
    d2 = df1.iloc[:, 2:]
    d2.columns = d1.columns
    
    df2 = pd.concat([d1, d2]).reset_index()
    df2 = df2.pivot(index='level_0', columns=[0, 1], values=2)
    df2.columns = df2.columns.map('-'.join)
    df2 = df2.reset_index(drop=True)
    

    替代方案:

    df2 = (
        (
            df['long string'].str.extractall(
                r'.*?([a-z]+)\s*?:\s*?\(([a-z]+):\s*(\d+)\s*([a-z]+):\s*(\d+)\)')
            .droplevel("match")
            .set_index(0, append=True)
            .apply(lambda x: x.values.reshape(-1, 2), axis=1)
            .explode()
            .apply(pd.Series)
            .add_prefix('val')
            .reset_index()
        ).pivot(index=['level_0'], columns=[0, 'val0'], values='val1')
    ).reset_index(drop=True)
    df2.columns = df2.columns.map('-'.join)
    

    输出:

      ha_la ha_tra hi_la hi_tra ho_la ho_tra
    0     2      1     2      1     2      1
    1     2      1     2      1     2      1
    2     2      1     2      1     2      1
    

    【讨论】:

      【解决方案2】:
      ndf = (df["long string"]
               .str.extractall(r"(ha|hi|ho):\s\((?:tra|la):\s(\d+)\s(?:tra|la):\s(\d+)\)")
               .droplevel("match")
               .set_index(0, append=True)
               .set_axis(["tra", "la"], axis=1)
               .unstack()
               .swaplevel(axis=1))
      ndf.columns = ndf.columns.map("-".join)
      
      • 使用regex 提取所需部分
      • 删除由称为matchextractall 引起的索引级别
      • 追加ha-hi-ho匹配作为索引(0是第一个捕获组)
      • 重命名剩余的列trala
      • ha-hi-ho 索引取消堆叠到列
      • 交换列中的ha-hi-hotra-la 级别的顺序,使ha-hi-ho 位于上层
      • 最后用连字符连接这些级别的列名

      得到

        ha-tra hi-tra ho-tra ha-la hi-la ho-la
      0      1      1      1     2     2     2
      1      1      1      1     2     2     2
      2      1      1      1     2     2     2
      

      【讨论】:

      • 这个答案很完美。对感兴趣的人提出后续问题:如果您的变量比(ha-ho-hi)多得多,但有 52 个呢?它们都具有以下结构:PA0.01、PB0.02、PA0.03。
      • @Charles 所以模式与这个问题不一样,例如PA: (tra: 0.01)?如果不是,也许你可以问另一个问题,人们可能会回答,因为这与这个问题有些不同。
      • 对不起,模式是相似的,只是它是 ha/ho/hi 的 52 个变体和 tra/la 的 4 个变体。例如,“已排序区域数据列表:ZoneData(zoneId=PA3.40, zoneLocationNumber=2672747, occupancyPercentage=61, numberOfHitsOnItemsFromTote=0,spurIsFull=false, isOnHold=false)\n”而不是“ha: (tra: 1拉:2)\n“
      • @Charles 我明白了,但您只想提取某些字段,例如以PA 开头的字段?另外,您能否使用这些新示例和所需的输出来编辑问题?
      • 我为自己的解决方案稍微调整了一下。如果您有兴趣,最终的正则表达式变为: .str.extractall(r"(PA0.02|PB0.09|PB3.47|PA1.14|PB1.21|PA3.44|PB1.24|PB3.45| PB2.34|PA0.03|PA2.30|PA0.01|PB2.33|PA3.40|PA0.06|PB1.23|PB3.49|PB1.20|PB2.31|PA1.13|PA3。 42|PA3.39|PA1.18|PB3.48|PB1.19|PB1.22|PB0.10|PA1.17|PA2.28|PA1.16|PA2.26|PA3.41|PA2.25| PA1.15|PA0.05|PA2.29|PB3.50|PB2.35|PB3.52|PB2.36|PB0.08|PB3.51|PB0.12|PB2.38|PA3.43|PB3。 46|PA2.27|PB2.32|PB0.07|PA0.04|PB2.37),\s(?:zoneLocationNumber)=(\d+),\soccupancyPercentage=(\d+), numberOfHitsOnItemsFromTote=(\d+) ")
      猜你喜欢
      • 1970-01-01
      • 2018-04-14
      • 2018-05-27
      • 2016-10-14
      • 2019-02-12
      • 1970-01-01
      • 2021-11-10
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多