Как поменять местами группу заголовков столбцов с их значениями в Pandas
у меня есть следующий фрейм данных:
a1 | a2 | a3 | a4
---------------------
Bob | Cat | Dov | Edd
Cat | Dov | Bob | Edd
Edd | Cat | Dov | Bob
и я хочу преобразовать его в
Bob | Cat | Dov | Edd
---------------------
a1 | a2 | a3 | a4
a3 | a1 | a2 | a4
a4 | a2 | a3 | a1
обратите внимание, что количество столбцов равно количеству уникальных значений, а количество и порядок строк сохраняются
3 ответов
1) подход:
более быстрой реализацией будет сортировка значений фрейма данных и выравнивание столбцов соответственно на основе полученных индексов после np.argsort
.
pd.DataFrame(df.columns[np.argsort(df.values)], df.index, np.unique(df.values))
применение np.argsort
дает нам данные, которые мы ищем:
df.columns[np.argsort(df.values)]
Out[156]:
Index([['a1', 'a2', 'a3', 'a4'], ['a3', 'a1', 'a2', 'a4'],
['a4', 'a2', 'a3', 'a1']],
dtype='object')
2) медленно обобщенных подход:
более обобщенный подход в то время как за счет некоторой скорости / эффективности было бы использовать apply
после создания dict
отображение строк/значений в таблице данных с соответствующими именами столбцов.
используйте конструктор dataframe позже после преобразования полученных рядов в их list
представление.
pd.DataFrame(df.apply(lambda s: dict(zip(pd.Series(s), pd.Series(s).index)), 1).tolist())
3) быстрее обобщенных подход:
после получения списка словарей от df.to_dict
+ orient='records'
, нам нужно поменять местами соответствующие пары ключей и значений, повторяя их в цикле.
pd.DataFrame([{val:key for key, val in d.items()} for d in df.to_dict('r')])
образец теста:
df = df.assign(a5=['Foo', 'Bar', 'Baz'])
оба эти подхода дают:
@piRSquared EDIT 1
обобщенное решение
def nic(df):
v = df.values
n, m = v.shape
u, inv = np.unique(v, return_inverse=1)
i = df.index.values
c = df.columns.values
r = np.empty((n, len(u)), dtype=c.dtype)
r[i.repeat(m), inv] = np.tile(c, n)
return pd.DataFrame(r, i, u)
1я хотел бы поблагодарить пользователя @piRSquared для придумывания действительно быстрой и обобщенной альтернативы на основе numpy soln.
вы можете изменить его с помощью stack и unstack с помощью замены значений и индекса:
df_swap = (df.stack() # reshape the data frame to long format
.reset_index(level = 1) # set the index(column headers) as a new column
.set_index(0, append=True) # set the values as index
.unstack(level=1)) # reshape the data frame to wide format
df_swap.columns = df_swap.columns.get_level_values(1) # drop level 0 in the column index
df_swap
numpy
+ pandas
v = df.values
n, m = v.shape
i = df.index.values
c = df.columns.values
# create series with values that were column values
# create multi index with first level from existing index
# and second level from flattened existing values
# then unstack
pd.Series(
np.tile(c, n),
[i.repeat(m), v.ravel()]
).unstack()
Bob Cat Dov Edd
0 a1 a2 a3 a4
1 a3 a1 a2 a4
2 a4 a2 a3 a1