Операция соединения строк в объектах python numpy или pandas - PullRequest
1 голос
/ 13 июля 2020

Я хочу объединить столбцы типа string в кадре данных pandas или numupy ndarray в последний столбец, например:

        a   b   c                          a   b   c   d
        ----------         --->            ---------------
        a   b   c                          a   b   c   a_b_c             
        d   e   f                          d   e   f   d_e_f
        g   h   i                          g   h   i   g_h_i

Я могу придумать два типичных варианта:

# Compose data
a = ['a','b','c']
b = ['d','e','f']
c = ['g','h','i']

pdf = pd.DataFrame([a,b,c], columns=['a','b','c'])


# One option
%%timeit
pdf.loc[:,'d'] = [i for i in map(lambda x: '_'.join([x.a, x.b, x.c]), pdf.itertuples())]
>>>1.08 ms ± 4.11 µs per loop (mean ± std. dev. of 7 runs, 1000 loops each)

# Another option
%%timeit
tmp=[]
for i in pdf.itertuples():
    tmp.append('_'.join([i.a, i.b, i.c]))

pdf.loc[:,'d'] = tmp
>>>1.08 ms ± 5.54 µs per loop (mean ± std. dev. of 7 runs, 1000 loops each)
 

Я понимаю, что может быть слишком мало данных, чтобы увидеть разницу между этими методами, но мой вопрос: есть ли более умный метод, встроенный в numpy или pandas, который я могу вызвать? Кроме того, есть ли какие-либо проблемы с любым из двух методов, о которых я подумал?

Спасибо!

Ответы [ 3 ]

4 голосов
/ 13 июля 2020

Вы можете попробовать эти 2 ниже, не обязательно использовать циклы:

df['combined'] = df['a'] + '_' + df['b'] + '_' + df['c']

или:

df['combined'] = df[['a', 'b', 'c']].agg('_'.join, axis=1)

   a  b  c combined
0  a  b  c    a_b_c
1  d  e  f    d_e_f
2  g  h  i    g_h_i
1 голос
/ 13 июля 2020

Я бы хотел предложить другой вариант:

pdf['a'].str.cat([pdf['b'], pdf['c']], sep='_')

Вывод:

0    a_b_c
1    d_e_f
2    g_h_i
Name: a, dtype: object

Время

# Compose data
a = ['a','b','c']
b = ['d','e','f']
c = ['g','h','i']

pdf = pd.DataFrame([a,b,c], columns=['a','b','c'])



def met_add(d):
    return df['a'] + '_' + df['b'] + '_' + df['c']

def met_agg_axis1(d):
    return  df[['a', 'b', 'c']].agg('_'.join, axis=1)

def met_str_cat(d):
    return pdf['a'].str.cat([pdf['b'], pdf['c']], sep='_')

def met_map_join(d):
    return pd.Series( [i for i in map(lambda x: '_'.join([x.a, x.b, x.c]), pdf.itertuples())])

def met_iter_join(d):
    tmp=[]
    for i in pdf.itertuples():
        tmp.append('_'.join([i.a, i.b, i.c]))
    return pd.Series(tmp)    

def met_numpy_add(d):
    return pd.Series(pdf['a'].to_numpy() + '_' + pdf['b'].to_numpy() + '_' + pdf['c'].to_numpy())

res = pd.DataFrame(
    index=[10, 30, 100, 300,1000, 3000, 10000, 30000, 100000, 300000],
    columns='met_add met_agg_axis1 met_str_cat met_map_join met_iter_join met_numpy_add'.split(),
    dtype=float
)

for i in res.index:
    d = pd.concat([pdf]*i).add_prefix('col')
    for j in res.columns:
        print(d.shape)
        stmt = '{}(d)'.format(j)
        setp = 'from __main__ import d, {}'.format(j)
        res.at[i, j] = timeit(stmt, setp, number=100)

res.plot(loglog=True, figsize=(10,8));

Вывод диаграммы:

введите описание изображения здесь

0 голосов
/ 13 июля 2020

Учитывая предоставленные вами данные и небольшое количество столбцов, с которыми вы работаете, вы можете [проще (но не масштабируемо)] просто использовать оператор + для столбцов, к которым вы sh присоединяете:

pdf['d'] = pdf['a'] + '_' + pdf['b'] + '_' + pdf['c']

Он не масштабируется, если у вас 200 столбцов, но он наверняка быстрее, чем два других метода, которые вы предлагаете. Используя его во фрейме данных 30000 строк, я получаю следующие временные результаты:

a = ['a','b','c']
b = ['d','e','f']
c = ['g','h','i']

pdf = pd.DataFrame([a,b,c]*10000, columns=['a','b','c'])

И вот результаты времени:

Method 1:  0.041734933853149414
Method 2:  0.04217410087585449
Method 3:  0.011157751083374023

Где методы 1 и 2 - предложенные, а третий - тот, что выше.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...