Подтвердить что ты не робот

Как создать DataFrame при сохранении порядка столбцов?

Как я могу создать DataFrame из нескольких массивов numpy, Pandas Series или Pandas DataFrame, сохраняя порядок столбцов?

Например, у меня есть два массива numpy, и я хочу объединить их как Pandas DataFrame.

foo = np.array( [ 1, 2, 3 ] )
bar = np.array( [ 4, 5, 6 ] )

Если я это сделаю, столбец bar будет первым, потому что dict не сохраняет порядок.

pd.DataFrame( { 'foo': pd.Series(foo), 'bar': pd.Series(bar) } )

    bar foo
0   4   1
1   5   2
2   6   3

Я могу это сделать, но мне становится скучно, когда мне нужно объединить множество переменных.

pd.DataFrame( { 'foo': pd.Series(foo), 'bar': pd.Series(bar) }, columns = [ 'foo', 'bar' ] )

EDIT: Есть ли способ указать переменные, которые нужно объединить, и упорядочить порядок столбцов за одну операцию? То есть, я не против использовать несколько строк для завершения всей операции, но я бы предпочёл не указывать переменные, которые нужно объединить несколько раз (так как я буду много менять код и это довольно склонно к ошибкам).

EDIT2: Еще один момент. Если я хочу добавить или удалить одну из переменных, которые нужно объединить, я хочу только добавить/удалить в одном месте.

4b9b3361

Ответ 1

Исходное решение: неправильное использование collections.OrderedDict

В моем исходном решении я предложил использовать OrderedDict из пакета collections в стандартной библиотеке python.

>>> import numpy as np
>>> import pandas as pd
>>> from collections import OrderedDict
>>>
>>> foo = np.array( [ 1, 2, 3 ] )
>>> bar = np.array( [ 4, 5, 6 ] )
>>>
>>> pd.DataFrame( OrderedDict( { 'foo': pd.Series(foo), 'bar': pd.Series(bar) } ) )

   foo  bar
0    1    4
1    2    5
2    3    6

Правильное решение: передача паттерна ключевых значений для сохранения заказа

Однако, как уже отмечалось, если нормальный словарь передается на OrderedDict, порядок все равно не сохраняется, так как порядок упорядочивается при построении словаря. Тем не менее, работа вокруг состоит в том, чтобы преобразовать список пар ключей-значений в значение OrderedDict, как предложено из этого сообщения SO:

>>> import numpy as np
>>> import pandas as pd
>>> from collections import OrderedDict
>>>
>>> a = np.array( [ 1, 2, 3 ] )
>>> b = np.array( [ 4, 5, 6 ] )
>>> c = np.array( [ 7, 8, 9 ] )
>>>
>>> pd.DataFrame( OrderedDict( { 'a': pd.Series(a), 'b': pd.Series(b), 'c': pd.Series(c) } ) )

   a  c  b
0  1  7  4
1  2  8  5
2  3  9  6

>>> pd.DataFrame( OrderedDict( (('a', pd.Series(a)), ('b', pd.Series(b)), ('c', pd.Series(c))) ) )

   a  b  c
0  1  4  7
1  2  5  8
2  3  6  9

Ответ 2

Используйте ключевое слово columns при создании DataFrame:

pd.DataFrame({'foo': foo, 'bar': bar}, columns=['foo', 'bar'])

Также обратите внимание, что вам не нужно создавать серию.

Ответ 3

Чтобы сохранить порядок столбцов, передайте свои массивы в виде списка кортежей в DataFrame.from_items:

>>> df = pd.DataFrame.from_items([('foo', foo), ('bar', bar)])

   foo  bar
0    1    4
1    2    5
2    3    6

Обновить

От панд 0.23 from_items устарела и будет удалена. Так проходят numpy массивы, используя from_dict. Чтобы использовать from_dict вам нужно передать элементы в виде словаря:

>>> from collections import OrderedDict as OrderedDict
>>> df = pd.DataFrame.from_dict(OrderedDict(zip(['foo', 'bar'], [foo, bar])))

Начиная с Python 3.7 вы можете зависеть от сохранения порядка вставки (см. Https://mail.python.org/pipermail/python-dev/2017-De December/151283.html) так:

>>> df = pd.DataFrame.from_dict(dict(zip(['foo', 'bar'], [foo, bar])))

или просто:

>>> df = pd.DataFrame(dict(zip(['foo', 'bar'], [foo, bar])))

Ответ 4

После создания вашего фрейма данных вы можете просто изменить порядок столбцов так, как вы хотите, используя

df= df[['foo','bar']]

Ответ 5

Я не могу прокомментировать, но как вы укажете порядок столбцов в первую очередь (поскольку вы не можете использовать обычный словарь)?

Если вы хотите сохранить упорядоченный словарь:

from collections import OrderedDict
import numpy as np
import pandas as pd

data = OrderedDict()
data['foo'] = np.array([1, 2, 3])
data['bar'] = np.array([4, 5, 6])

df = pd.DataFrame(data)

Если у вас есть список ключей для заказа:

data = {key: value for key, value in data.iteritems()}
df = pd.concat(data.values(), keys=['foo', 'bar'], axis=1)

@tfv ответ, скорее всего, самый сжатый способ сделать то, что вы хотите.

Ответ 6

>>> pd.concat([pd.Series(eval(col), name=col) for col in ['foo', 'bar']], axis=1)
   foo  bar
0    1    4
1    2    5
2    3    6

Это работает с использованием eval. Ваш список имен столбцов должен соответствовать соответствующему имени переменной.

>>> eval('foo')
array([1, 2, 3])

Ответ 7

Это может быть другой способ приблизиться к нему:

foo = np.array( [ 1, 2, 3 ] )
bar = np.array( [ 4, 5, 6 ] )
stacked = np.vstack((x,y)).T
stacked
array([[1, 4],
       [2, 5],
       [3, 6]])

new_df = pd.DataFrame(stacked, columns = ['foo', 'bar'] )
new_df
   foo  bar
0   1   4
1   2   5
2   3   6

Ответ 8

Сделайте dataframe только с данными в нем и перенесите его.

Затем добавьте столбцы.

>>> foo = np.array( [ 1, 2, 3 ] )
>>> bar = np.array( [ 4, 5, 6 ] )
>>>     
>>> df = pd.DataFrame([foo, bar]).T
>>> df.columns = ['foo','bar']
>>> df
  foo bar
0  1   4
1  2   5
2  3   6

Ответ 9

Другим отрывочным решением может быть передача X_ в заголовок столбца, где X - номер порядка столбца:

pd.DataFrame( { '2_foo': pd.Series(foo), '1_bar': pd.Series(bar) } )

И после этого вы можете использовать столбцы или что-то еще, чтобы снова переименовать столбцы! Менее пифонический код в мире!!!

Удачи!

Ответ 10

Я сделал следующее:

# Creating list of dict
list_of_dicts = ({'key1':'valueA', 'key2':'valueB},{'key1':'valueC', 'key2':'valueD}')

#getting list of keys from the dict
keys_list = list(list_of_dicts.keys())

# and finally
df = pd.DataFrame(list_of_dicts, columns = keys_list)

Работал отлично для меня.