복붙노트

[PYTHON] 일련의 문자열 분해 / 스택

PYTHON

일련의 문자열 분해 / 스택

나는 가지고있다:

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

   col1  col2
0  asdf     1
1    xy     2
2     q     3

col2의 각 요소 별 int와 함께 col1의 문자열에서 각 문자의 "조합 상품"을 가져오고 싶습니다. 나는

  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)

더 효과적인 해결 방법은 무엇입니까?

해결법

  1. ==============================

    1.list + str.join과 np.repeat 사용하기 -

    list + str.join과 np.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의 타이밍을 시도했지만이 데이터 세트에서 너무 오래 걸렸습니다.

  2. ==============================

    2.

    pd.DataFrame([(letter, i) 
                  for letters, i in zip(df['col1'], df['col2']) 
                  for letter in letters],
                 columns=df.columns)
    
  3. ==============================

    3.

    In [86]: df.col1.str.extractall(r'(.)') \
               .reset_index(level=1, drop=True) \
               .join(df['col2']) \
               .reset_index(drop=True)
    Out[86]:
       0  col2
    0  a     1
    1  s     1
    2  d     1
    3  f     1
    4  x     2
    5  y     2
    6  q     3
    
  4. ==============================

    4.트릭 목록에서 :-)

    트릭 목록에서 :-)

    df.col1=df.col1.apply(list)
    df
    Out[489]: 
               col1  col2
    0  [a, s, d, f]     1
    1        [x, y]     2
    2           [q]     3
    pd.DataFrame({'col1':np.concatenate(df.col1.values),'col2':df.col2.repeat(df.col1.apply(len))})
    Out[490]: 
      col1  col2
    0    a     1
    0    s     1
    0    d     1
    0    f     1
    1    x     2
    1    y     2
    2    q     3
    
  5. ==============================

    5.하나 더:)

    하나 더:)

    df.set_index('col2').col1.apply(lambda x: pd.Series(list(x))).stack()\
    .reset_index(1,drop = True).reset_index(name = 'col1')
    
        col2    col1
    0   1       a
    1   1       s
    2   1       d
    3   1       f
    4   2       x
    5   2       y
    6   3       q
    
  6. ==============================

    6.목록 이해력과 영리한 풀기가있는 일반 솔루션 :

    목록 이해력과 영리한 풀기가있는 일반 솔루션 :

    pd.DataFrame(
        [[x] + b for a, *b in df.values for x in a],
        columns=df.columns
    )
    
      col1  col2
    0    a     1
    1    s     1
    2    d     1
    3    f     1
    4    x     2
    5    y     2
    6    q     3
    
  7. from https://stackoverflow.com/questions/48197234/explode-stack-a-series-of-strings by cc-by-sa and MIT license