Самый быстрый / наилучший способ добавления столбцов в фрейм данных pandas из набора массивов numpy с одинаковой длиной df?

#python #pandas #performance #dataframe #coding-style

#python #pandas #Производительность #фрейм данных #стиль кодирования

Вопрос:

Вероятно, это простой вопрос, я искал, но не могу найти решение.

Мой код выглядит примерно так

 data_df = pd.DataFrame([
    ['2012-02-22', '3', 'a', 6],
    ['2012-02-23', '3.2', 'g', 8],
    ['2012-02-24', '5.2', 'l', 2],
    ['2012-02-25', '1.4', 'i', 4]],
    columns=['date', '1', '2', '3'])
dict_a = {
    'a': np.array([False, True, False, False], dtype='bool'),
    'b': np.array([True, True, False, False], dtype='bool'),
    'c': np.array([False, True, True, False], dtype='bool'),
}
  

и я хотел бы иметь df, подобный этому

               1  2  3      a      b      c
date                                      
2012-02-22    3  a  6  False   True  False
2012-02-23  3.2  g  8   True   True   True
2012-02-24  5.2  l  2  False  False   True
2012-02-25  1.4  i  4  False  False  False
  

до сих пор лучший способ, который я нашел, это этот, но мне он кажется банальным

 data_df = data_df.set_index('date')
df_dict = pd.DataFrame.from_dict(dict_a)
df_dict['date'] = data_df.index
df_dict = df_dict.set_index('date')
df_new = pd.merge(data_df, df_dict, left_index=True, right_index=True)
  

есть более быстрый / лучший способ добиться этого?

РЕДАКТИРОВАТЬ: Результаты

Спасибо вам всем за очень быстрые ответы. Я немного подсчитал время, и (пока) похоже, что с заданными данными самый быстрый — 1-й.

 def df_new1():
    data_df = pd.DataFrame([
        ['2012-02-22', '3', 'a', 6],
        ['2012-02-23', '3.2', 'g', 8],
        ['2012-02-24', '5.2', 'l', 2],
        ['2012-02-25', '1.4', 'i', 4]],
        columns=['date', '1', '2', '3'])

    dict_a = {
        'a1': np.array([False, True, False, False], dtype='bool'),
        'b1': np.array([True, True, False, False], dtype='bool'),
        'c1': np.array([False, True, True, False], dtype='bool'),
    }
    return pd.concat((data_df, pd.DataFrame(dict_a)), axis=1).set_index('date')


def df_new2():
    data_df = pd.DataFrame([
        ['2012-02-22', '3', 'a', 6],
        ['2012-02-23', '3.2', 'g', 8],
        ['2012-02-24', '5.2', 'l', 2],
        ['2012-02-25', '1.4', 'i', 4]],
        columns=['date', '1', '2', '3'])

    dict_a = {
        'a1': np.array([False, True, False, False], dtype='bool'),
        'b1': np.array([True, True, False, False], dtype='bool'),
        'c1': np.array([False, True, True, False], dtype='bool'),
    }
    return data_df.assign(**dict_a).set_index('date')


def df_new3():
    data_df = pd.DataFrame([
        ['2012-02-22', '3', 'a', 6],
        ['2012-02-23', '3.2', 'g', 8],
        ['2012-02-24', '5.2', 'l', 2],
        ['2012-02-25', '1.4', 'i', 4]],
        columns=['date', '1', '2', '3'])

    dict_a = {
        'a1': np.array([False, True, False, False], dtype='bool'),
        'b1': np.array([True, True, False, False], dtype='bool'),
        'c1': np.array([False, True, True, False], dtype='bool'),
    }
    return data_df.join(pd.DataFrame(dict_a)).set_index('date')


def df_new4():
    data_df = pd.DataFrame([
        ['2012-02-22', '3', 'a', 6],
        ['2012-02-23', '3.2', 'g', 8],
        ['2012-02-24', '5.2', 'l', 2],
        ['2012-02-25', '1.4', 'i', 4]],
        columns=['date', '1', '2', '3'])

    dict_a = {
        'a1': np.array([False, True, False, False], dtype='bool'),
        'b1': np.array([True, True, False, False], dtype='bool'),
        'c1': np.array([False, True, True, False], dtype='bool'),
    }
    for keys in dict_a:
        data_df[keys] = dict_a[keys]
    return data_df.set_index('date')

print('df_new1', timeit(df_new1, number=1000))
print('df_new2', timeit(df_new2, number=1000))
print('df_new3', timeit(df_new3, number=1000))
print('df_new4', timeit(df_new4, number=1000))
  
 df_new1 2.0431520210004237
df_new2 2.6708478379987355
df_new3 2.4773063749998983
df_new4 2.910699995998584
  

Ответ №1:

pd.concat вкл axis=1 , затем установите индекс

 pd.concat((data_df,pd.DataFrame(dict_a)),axis=1).set_index("date")

              1  2  3      a      b      c
date                                      
2012-02-22    3  a  6  False   True  False
2012-02-23  3.2  g  8   True   True   True
2012-02-24  5.2  l  2  False  False   True
2012-02-25  1.4  i  4  False  False  False
  

Комментарии:

1. Похоже, что это самый быстрый код с заданными данными. Спасибо за вашу помощь!

Ответ №2:

Почему бы просто не:

 for keys in dict_a:
    data_df[keys]=dict_a[keys]
  

Обратите внимание, что длина данных в dict должна быть равна длине данных в dataframe

Комментарии:

1. Я принимаю это как результат, который на данный момент выглядит как самый быстрый. Спасибо за вашу помощь!

2. Извините, я допустил ошибку. Я забыл добавить .set_index('date') в конце, как это предусмотрено в требуемом коде. Похоже, что это небольшое изменение добавило много работы, и теперь код самый медленный. :-/

Ответ №3:

Попробуйте DataFrame.assign :

 data_df.assign(**dict_a)
  

          date    1  2  3      a      b      c
0  2012-02-22    3  a  6  False   True  False
1  2012-02-23  3.2  g  8   True   True   True
2  2012-02-24  5.2  l  2  False  False   True
3  2012-02-25  1.4  i  4  False  False  False
  

Комментарии:

1. Это очень элегантно и чисто, я, вероятно, буду использовать его как наиболее краткий. Спасибо!

Ответ №4:

Используйте join :

 data_df.join(pd.DataFrame(dict_a)).set_index('date')
              1  2  3      a      b      c
date                                      
2012-02-22    3  a  6  False   True  False
2012-02-23  3.2  g  8   True   True   True
2012-02-24  5.2  l  2  False  False   True
2012-02-25  1.4  i  4  False  False  False