Как создать 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: Еще один момент. Если я хочу добавить или удалить одну из переменных, которые нужно объединить, я хочу только добавить/удалить в одном месте.
Ответы
Ответ 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)
Работал отлично для меня.