【问题标题】:Split a column which is separated by comma based on certain condition in pandas根据熊猫中的某些条件拆分以逗号分隔的列
【发布时间】:2021-07-02 09:41:40
【问题描述】:

我有一个数据框

df = pd.DataFrame([["A","a*k,x*k,z,c*m,r,s,f*f,e*d"], ["B","h*t,y,a,w*b,Z,c*b,i*t,f*f"]], columns=["id","c1"])

我想在以下条件下拆分以逗号分隔的列 c1:

  1. 只保留那些带有 * 的字符串
  2. 如果 * 之后如果有任何重复的字母,则不要考虑 2ns 字符串取下一个。
  3. 保留唯一的前 3 个字符串并将它们拆分为 * 并制作 2 个单独的列

示例: 对于 c1 中的第一行,

  1. z,r,s 没有 *,所以删除它们
  2. 在 a*k 和 x *k 中,k 是重复的,所以保留第一个
  3. 所以前 3 名将是 a*k、c *m、f *f,将其拆分为 2 列 c2、a、c、f 和 c3 k、m、f。

预期输出:

df_out = pd.DataFrame([["A","a*k,x*k,z,c*m,r,s,f*f,e*d","a,c,f","k,m,f"], ["B","h*t,y,a,w*b,Z,c*b,i*b,f*f","h,w,f","t,b,f"]], columns=["id","c1","c2","c3"])

怎么做?

【问题讨论】:

    标签: python python-3.x pandas python-2.7 dataframe


    【解决方案1】:

    您可以使用 pd.Series.str.extractallGroupBy.apply 删除重复项并获取前 3 个字符串。

    out = df["c1"].str.extractall(r"(.)\*(.)").groupby(level=0)
    df[["c2", "c3"]] = out.apply(
        lambda x: x.drop_duplicates(subset=1).head(3).agg(",".join)
    )
    
    # df
      id                         c1     c2     c3
    0  A  a*k,x*k,z,c*m,r,s,f*f,e*d  a,c,f  k,m,f
    1  B  h*t,y,a,w*b,Z,c*b,i*t,f*f  h,w,f  t,b,f
    

    【讨论】:

    • 如果我需要输出而不是 c2 中的 a、c、f,则更改为 a *k、c *m、f *f 在 c2 和 c3 中未更改 k、m、f。需要做哪些修改?
    • @Chethan 请不要在有人回答后更改问题。它完全使回答者付出的努力无效。
    • For what modification need to be done? 你想要c1a*k, c*m, f*f 然后直接用这个正则表达式r'(.\*.)' 提取,你已经被* 分割,删除重复项,取第一个三个。恕我直言,值得提出一个新问题。 @Chethan
    【解决方案2】:

    首先定义一个函数来生成2个新列:

    def newCols(lst):
        return pd.Series(filter(lambda tt: tt.find('*') >= 0, lst))\
            .str.split('*', expand=True)\
            .rename(columns={0: 'c2', 1: 'c3'})\
            .drop_duplicates(subset='c3').iloc[:3]\
            .apply(lambda col: ','.join(col))
    

    然后生成结果为:

    result = df.join(df.c1.str.split(',').apply(newCols))
    

    结果是:

      id                         c1     c2     c3
    0  A  a*k,x*k,z,c*m,r,s,f*f,e*d  a,c,f  k,m,f
    1  B  h*t,y,a,w*b,Z,c*b,i*t,f*f  h,w,f  t,b,f
    

    newCols中的处理步骤

    • pd.Series(filter(lambda tt: tt.find('*') >= 0, lst)) - 创建 Series 来自包含星号的元素。
    • str.split('*', expand=True) - 将其转换为 DataFrame。
    • rename(columns={0: 'c2', 1: 'c3'}) - 将列重命名为 'c2''c3'
    • drop_duplicates(subset='c3') - 删除重复行(具有相同的 c3)。
    • iloc[:3] - 只取 3 个初始行。
    • apply(lambda col: ','.join(col) - 将每一列连接成一个字符串。

    尝试将它们作为“不断扩展的代码”执行,在:

    lst = ['a*k', 'x*k', 'z', 'c*m', 'r', 's', 'f*f', 'e*d']
    

    (来自第一个源行的结果)。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2023-01-11
      • 1970-01-01
      • 2022-10-07
      • 2023-03-13
      • 2019-05-17
      • 2022-01-21
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多