Nesting (explosion) panda series

发布于 2021-01-29 17:51:30

我有:

df = pd.DataFrame({'col1': ['asdf', 'xy', 'q'], 'col2': [1, 2, 3]})

   col1  col2
0  asdf     1
1    xy     2
2     q     3

我想从in中的字符串中提取每个字母的“组合乘积”,并将in中的col1每个elementwise int提取col2。即:

  col1  col2
0    a    1
1    s    1
2    d    1
3    f    1
4    x    2
5    y    2
6    q    3

当前方法:

from itertools import product

pieces = []
for _, s in df.iterrows():
    letters = list(s.col1)
    prods = list(product(letters, [s.col2]))
    pieces.append(pd.DataFrame(prods))

pd.concat(pieces)

还有更有效的解决方法吗?

关注者
0
被浏览
43
1 个回答
  • 面试哥
    面试哥 2021-01-29
    为面试而生,有面试问题,就找面试哥。

    使用list+str.joinnp.repeat-

    pd.DataFrame(
    {
         'col1' : list(''.join(df.col1)), 
         'col2' : df.col2.values.repeat(df.col1.str.len(), axis=0)
    })
    
      col1  col2
    0    a     1
    1    s     1
    2    d     1
    3    f     1
    4    x     2
    5    y     2
    6    q     3
    

    无需更改 任何 解决方案即可轻松实现针对 任意数量列的 通用解决方案-

    i = list(''.join(df.col1))
    j = df.drop('col1', 1).values.repeat(df.col1.str.len(), axis=0)
    
    df = pd.DataFrame(j, columns=df.columns.difference(['col1']))
    df.insert(0, 'col1', i)
    
    df
    
      col1 col2
    0    a    1
    1    s    1
    2    d    1
    3    f    1
    4    x    2
    5    y    2
    6    q    3
    

    性能

    df = pd.concat([df] * 100000, ignore_index=True)
    
    
    
    # MaxU's solution
    
    %%timeit
    df.col1.str.extractall(r'(.)') \
               .reset_index(level=1, drop=True) \
               .join(df['col2']) \
               .reset_index(drop=True)
    
    1 loop, best of 3: 1.98 s per loop
    
    
    
    # piRSquared's solution
    
    %%timeit
    pd.DataFrame(
         [[x] + b for a, *b in df.values for x in a],
         columns=df.columns
    )
    
    1 loop, best of 3: 1.68 s per loop
    
    
    
    # Wen's solution
    
    %%timeit
    v = df.col1.apply(list)
    pd.DataFrame({'col1':np.concatenate(v.values),'col2':df.col2.repeat(v.apply(len))})
    
    1 loop, best of 3: 835 ms per loop
    
    
    
    # Alexander's solution
    
    %%timeit
    pd.DataFrame([(letter, i) 
                  for letters, i in zip(df['col1'], df['col2']) 
                  for letter in letters],
                 columns=df.columns)
    
    1 loop, best of 3: 316 ms per loop
    
    
    
    %%timeit
    pd.DataFrame(
    {
         'col1' : list(''.join(df.col1)), 
         'col2' : df.col2.values.repeat(df.col1.str.len(), axis=0)
    })
    
    10 loops, best of 3: 124 ms per loop
    

    我尝试对Vaishali进行计时,但是在此数据集上花费的时间太长。



知识点
面圈网VIP题库

面圈网VIP题库全新上线,海量真题题库资源。 90大类考试,超10万份考试真题开放下载啦

去下载看看