2016-11-02 2 views
1

Имея кадр данных, как:Объединить столбцы в DataFrame

import pandas 

df = pandas.DataFrame({'a': [1, 2, 3], 'b': [9, 8, 7], 'c': [4, 5, 6]}) 
df 

enter image description here

Я хотел бы иметь фрейм данных с:

  • Фактором/колонке категории ['a', 'b']. Имя этой колонки, мне все равно.
  • Столбец, который имеет старое значение столбца a или b, в зависимости от фактора ['a', 'b']. Имя этой колонки, мне все равно.
  • Сохранение значений и имени столбца c (фактический кадр данных содержит несколько столбцов, которые я хотел бы сохранить).
  • Меня не интересует порядок столбцов в результирующем фрейме данных, а также если некоторые (или любые) из них установлены как индекс.

Это пример того, что я хотел бы получить:

df['name_a'] = 'a' 
df['name_b'] = 'b' 

c0 = pandas.concat([df['name_a'], df['name_b']]) 
c1 = pandas.concat([df['a'], df['b']]) 
c2 = pandas.concat([df['c'], df['c']]) 

newdf = pandas.concat([c0, c1, c2], axis=1) 
newdf 

enter image description here

Есть ли лучший способ добиться того же результата? Я чувствую, что это очень уродливо. Возможно, функция pandas, которую я пропускаю, и делает код намного чище и понятным?

ответ

1

Я думаю, что вам нужно melt:

print (pd.melt(df,id_vars='c', var_name='0', value_name='1')) 
    c 0 1 
0 4 a 1 
1 5 a 2 
2 6 a 3 
3 4 b 9 
4 5 b 8 
5 6 b 7 

Другое решение с stack с sort_values:

df1 = df.set_index('c').stack().reset_index().sort_values('level_1') 
df1.columns = ['c', '0','1'] 
print (df1) 
    c 0 1 
0 4 a 1 
2 5 a 2 
4 6 a 3 
1 4 b 9 
3 5 b 8 
5 6 b 7 

Более общее решение - использовать list comprehension для фильтра все столбцы, которые не являются a и b к переменной cols :

cols = [col for col in df.columns if col not in ['a','b']] 
print (cols) 
['c'] 

print (pd.melt(df,id_vars=cols, var_name='0', value_name='1')) 
    c 0 1 
0 4 a 1 
1 5 a 2 
2 6 a 3 
3 4 b 9 
4 5 b 8 
5 6 b 7 

образца с добавлением другого столбца g:

df = pd.DataFrame({'a': [1, 2, 3], 
        'b': [9, 8, 7], 
        'c': [4, 5, 6], 
        'g': [0, 1, 7]}) 

print (df) 
    a b c g 
0 1 9 4 0 
1 2 8 5 1 
2 3 7 6 7 

cols = [col for col in df.columns if col not in ['a','b']] 
print (cols) 
['c', 'g'] 

Faster решение с numpy.setdiff1d:

cols = np.setdiff1d(df.columns, ['a','b']).tolist() 
print (cols) 
['c', 'g'] 

print (pd.melt(df,id_vars=cols, var_name='0', value_name='1')) 
    c g 0 1 
0 4 0 a 1 
1 5 1 a 2 
2 6 7 a 3 
3 4 0 b 9 
4 5 1 b 8 
5 6 7 b 7 
+0

Спасибо, это выглядит довольно хорошо! Однако обратите внимание, что «* в фактическом кадре данных есть несколько столбцов, которые я хотел бы сохранить *» (т. Е .: много столбцов 'c'). Есть ли способ сделать это, используя 'a' и' b' в качестве параметров вместо 'c'? ('a' и' b' всегда 2, но есть много столбцов 'c' с разными именами, и я хотел бы сохранить их все). – Peque

+0

уверен, дайте мне сек. – jezrael

+0

Проверьте мой ответ. – jezrael

Смежные вопросы