【问题标题】:Split rows to create new rows in Pandas Dataframe with same other row values拆分行以在 Pandas Dataframe 中创建具有相同其他行值的新行
【发布时间】:2021-11-28 21:25:52
【问题描述】:

我有一个 pandas 数据框,其中一列文本字符串包含多个逗号分隔的值。我想拆分每个字段并仅在逗号数> = 2的情况下为每个条目创建一个新行。例如,a应该变为b:

In [7]: a
Out[7]: 
    var1     var2   var3
0  a,b,c,d     1     X1
1  a,b,c,d     1     X2
2  a,b,c,d     1     X3
3  a,b,c,d     1     
4  e,f,g       2     Y1
5  e,f,g       2     Y2
6  e,f,g       2     
7  h,i         3     Z1
In [8]: b
Out[8]: 
     var1  var2   var3
0    a,d     1     X1
1    b,d     1     X2
3    c,d     1     X3
4    e,g     2     Y1
5    f,g     2     Y2
6    h,i     3     Z1

【问题讨论】:

  • 我不明白你如何在 a,b,c,d 中选择哪一个是 var,可以是 ab, ac, ad, bd, bc, bd, cd。 .
  • @Tomer S 它必须与最后一个元素配对。前 1,2,3....n-1 个元素中的每一个都必须与第 n 个元素配对。

标签: python pandas split explode


【解决方案1】:

您可以使用自定义函数:

def custom_split(r):
    if r['var3']:
        s = r['var1']
        i = int(r['var3'][1:])-1
        l = s.split(',')
        return l[i]+','+l[-1]

df['var1'] = df.apply(custom_split, axis=1)
df = df.dropna()

输出:

  var1  var2 var3
0  a,d     1   X1
1  b,d     1   X2
2  c,d     1   X3
4  e,g     2   Y1
5  f,g     2   Y2
7  h,i     3   Z1

【讨论】:

    【解决方案2】:
    df['cc'] = df.groupby('var1')['var1'].cumcount()
    df['var1'] = df['var1'].str.split(',')
    df['var1'] = df[['cc','var1']].apply(lambda x: x['var1'][x['cc']]+','+x['var1'][-1],axis=1)
    df = df.dropna().drop(columns=['cc']).reset_index(drop=True)
    df 
    

    【讨论】:

    • 三个答案怎么都被否决了???
    • 一定是心情不好的人,我给你点赞来弥补
    • 好的。我还给你一个。 ;-)
    【解决方案3】:

    您可以通过将逗号上的var1 拆分为列表来实现。 var3 中的整数减 1 可以解释为 var1 中列表中要保留的项目的索引:

    import pandas as pd
    import io
    
    data = '''    var1     var2   var3
    0  a,b,c,d     1     X1
    1  a,b,c,d     1     X2
    2  a,b,c,d     1     X3
    3  a,b,c,d     1     
    4  e,f,g       2     Y1
    5  e,f,g       2     Y2
    6  e,f,g       2     
    7  h,i         3     Z1'''
    
    df = pd.read_csv(io.StringIO(data), sep = r'\s\s+', engine='python')
    df['var1'] = df["var1"].str.split(',').apply(lambda x: [[i,x[-1]] for i in x[:-1]]) #split the string to list and create combinations of all items with the last item in the list
    df = df[df['var3'].notnull()] # drop rows where var3 is None
    df['var1'] = df.apply(lambda x: x['var1'][0 if not x['var3'] else int(x['var3'][1:])-1], axis=1) #keep only the element in the list in var1 where the index is the integer in var3 minus 1
    

    输出:

    var1 var2 var3
    0 ['a', 'd'] 1 X1
    1 ['b', 'd'] 1 X2
    2 ['c', 'd'] 1 X3
    4 ['e', 'g'] 2 Y1
    5 ['f', 'g'] 2 Y2
    7 ['h', 'i'] 3 Z1

    运行df['var1'] = df['var1'].str.join(',')var1 重新转换为字符串。

    【讨论】:

    • 我喜欢你在应用程序中使用索引的方式,而我使用 cumcount。我认为您通过在 var3 中删除 null 来删除最后一个(额外)项目,而我基于 nan 删除(如果单元格有 nan,则存在危险)。顺便说一句,你用什么IDE?它会生成一个类似 excel 的表格。
    • @EBDS stackoverflow 可以解析 markdown 表。只需复制并粘贴print(df.to_markdown()) 的输出即可。确保表格和前面的文本之间有一个空行,否则 SO 不会解析它。
    猜你喜欢
    • 2021-09-20
    • 1970-01-01
    • 2014-02-09
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-11-02
    • 2020-03-10
    相关资源
    最近更新 更多