2013-09-11 5 views
3

У меня возникла проблема создания и изменения набора данных. Я посмотрел на функцию pandas groupby и подумал, что это может помочь мне это сделать, но я неопытен, чтобы это произошло. Я создал пример моей проблемы ниже: мой ДФ:Pandas stack/groupby, чтобы создать новый Dataframe

 vehicle color a b c d A1 A2 A3 B1 B2 B3 C1 C2 C3 D1 D2 D3 
resp                   
1  bike green 5 4 1 3 3 4 5 3 5 3 NaN NaN NaN NaN NaN NaN 
2  walk red 5 3 3 3 4 5 3 3 5 4 NaN NaN NaN NaN NaN NaN 
3  car green 4 2 3 3 4 3 5 4 5 5 NaN NaN NaN NaN NaN NaN 
4  car blue 4 5 4 4 NaN NaN NaN NaN NaN NaN 5 5 5 3 3 4 
5  bus black 2 4 4 3 NaN NaN NaN 2 3 3 2 2 1 NaN NaN NaN 
6  car red 4 2 3 3 3 4 4 NaN NaN NaN 4 4 4 NaN NaN NaN 
7  bus blue 5 5 2 3 3 3 5 4 3 2 NaN NaN NaN NaN NaN NaN 
8  walk red 3 3 4 3 NaN NaN NaN 5 5 5 5 3 3 NaN NaN NaN 
9  car blue 5 3 4 3 3 3 3 NaN NaN NaN 4 3 4 NaN NaN NaN 

Набор данных содержит респондентов и ответы на questionare. То, что я хотел бы сделать, - создать новый dataframe с индексом и данными о том, как респонденты ответили перестроенным. Данные в столбцах a, b, c, d, транспортном средстве и цвете складываются для респондентов (надеюсь, что это правильный способ выразить это) в новой информационной кадре. Также значения из столбцов A-C находятся в новом фрейме под столбцами BL_val. Заполнены только те данные, которые соответствуют букве «Столица» (A1-D3) на малую букву (a, b, c, d). Остальные - NAN.

Я хотел бы создать новый datafram от этого и Шоул выглядеть следующим образом:

DS:

 vehicle color sl sl_val BL_val1 BL_val2 BL_val3 
resp              
1  bike green a  5  3  4  5 
1  bike green b  4  3  5  3 
1  bike green c  1  NaN  NaN  NaN 
1  bike green d  3  NaN  NaN  NaN 
2  walk red a  5  4  5  3 
2  walk red b  3  3  5  4 
2  walk red c  3  NaN  NaN  NaN 
2  walk red d  3  NaN  NaN  NaN 
3  car green a  4  4  3  5 
3  car green b  2  4  5  5 
3  car green c  3  NaN  NaN  NaN 
3  car green d  3  NaN  NaN  NaN 
4  car blue a  4  NaN  NaN  NaN 
4  car blue b  5  NaN  NaN  NaN 
4  car blue c  4  5  5  5 
4  car blue d  4  3  3  4 
5  bus black a  2  NaN  NaN  NaN 
5  bus black b  4  2  3  3 
5  bus black c  4  2  2  1 
5  bus black d  3  NaN  NaN  NaN 
6  car red a  4  3  4  4 
6  car red b  2  NaN  NaN  NaN 
6  car red c  3  4  4  4 
6  car red d  3  NaN  NaN  NaN 
7  bus blue a  5  3  3  5 
7  bus blue b  5  4  3  2 
7  bus blue c  2  NaN  NaN  NaN 
7  bus blue d  3  NaN  NaN  NaN 
8  walk red a  3  NaN  NaN  NaN 
8  walk red b  3  5  5  5 
8  walk red c  4  5  3  3 
8  walk red d  3  NaN  NaN  NaN 
9  car blue a  5  3  3  3 
9  car blue b  3  NaN  NaN  NaN 
9  car blue c  4  4  3  4 
9  car blue d  NaN  NaN  NaN  NaN 

мне очень нужна помощь в этом, я не могу понять это !!

ответ

3

Возможно, существует более удобный способ сделать это, но я нахожу, что шаблон использования groupby для создания групп, выполнения явных операций над ними и последующей рекомбинации часто является простым способом получить то, что я хочу. Конечно, я мог бы потратить полчаса на что-то более элегантное, но тогда у меня не было бы времени, чтобы болтаться на SO ..

В любом случае, как насчет этого?

df = df.set_index(["resp", "vehicle", "color"]) 

grouped = df.groupby(lambda x: x[0].lower(), axis=1) 

new_grouped = [] 
for key, group in grouped: 
    group.columns = ["sl_val"] + ["BL_val{}".format(i) for i in range(1,4)] 
    group["sl"] = key 
    new_grouped.append(group) 

df2 = pd.concat(new_grouped).reset_index() 

df2 = df2.sort(["resp", "vehicle", "color"]).set_index("resp") 
df2 = df2[["vehicle", "color", "sl"] + [k for k in df2.columns if "_" in k]] 

Начиная с

>>> df = df.set_index(["resp", "vehicle", "color"]) 
>>> df 
        a b c d A1 A2 A3 B1 B2 B3 C1 C2 C3 D1 D2 D3 
resp vehicle color                
1 bike green 5 4 1 3 3 4 5 3 5 3 NaN NaN NaN NaN NaN NaN 
2 walk red 5 3 3 3 4 5 3 3 5 4 NaN NaN NaN NaN NaN NaN 
3 car  green 4 2 3 3 4 3 5 4 5 5 NaN NaN NaN NaN NaN NaN 
4 car  blue 4 5 4 4 NaN NaN NaN NaN NaN NaN 5 5 5 3 3 4 
5 bus  black 2 4 4 3 NaN NaN NaN 2 3 3 2 2 1 NaN NaN NaN 
6 car  red 4 2 3 3 3 4 4 NaN NaN NaN 4 4 4 NaN NaN NaN 
7 bus  blue 5 5 2 3 3 3 5 4 3 2 NaN NaN NaN NaN NaN NaN 
8 walk red 3 3 4 3 NaN NaN NaN 5 5 5 5 3 3 NaN NaN NaN 
9 car  blue 5 3 4 3 3 3 3 NaN NaN NaN 4 3 4 NaN NaN NaN 

Мы можем сгруппировать по начальной буквой в нижнем регистре:

>>> grouped = df.groupby(lambda x: x[0].lower(), axis=1) 

продуцента кучу групп, которые выглядят как:

>>> next(iter(grouped)) 
('a',      a A1 A2 A3 
resp vehicle color    
1 bike green 5 3 4 5 
2 walk red 5 4 5 3 
3 car  green 4 4 3 5 
4 car  blue 4 NaN NaN NaN 
5 bus  black 2 NaN NaN NaN 
6 car  red 4 3 4 4 
7 bus  blue 5 3 3 5 
8 walk red 3 NaN NaN NaN 
9 car  blue 5 3 3 3) 

Затем мы просто меняем имена, добавляем столбец "sl" и рекомбинируем их, используя pd.concat. Последние бит просто соответствуют вашему желаемому порядку.

Окончательный результат:

>>> df2 
    vehicle color sl sl_val BL_val1 BL_val2 BL_val3 
resp              
1  bike green a  5  3  4  5 
1  bike green b  4  3  5  3 
1  bike green c  1  NaN  NaN  NaN 
1  bike green d  3  NaN  NaN  NaN 
2  walk red a  5  4  5  3 
2  walk red b  3  3  5  4 
2  walk red c  3  NaN  NaN  NaN 
2  walk red d  3  NaN  NaN  NaN 
3  car green a  4  4  3  5 
3  car green b  2  4  5  5 
3  car green c  3  NaN  NaN  NaN 
3  car green d  3  NaN  NaN  NaN 
4  car blue a  4  NaN  NaN  NaN 
4  car blue b  5  NaN  NaN  NaN 
4  car blue c  4  5  5  5 
4  car blue d  4  3  3  4 
5  bus black a  2  NaN  NaN  NaN 
5  bus black b  4  2  3  3 
5  bus black c  4  2  2  1 
5  bus black d  3  NaN  NaN  NaN 
6  car red a  4  3  4  4 
6  car red b  2  NaN  NaN  NaN 
6  car red c  3  4  4  4 
6  car red d  3  NaN  NaN  NaN 
7  bus blue a  5  3  3  5 
7  bus blue b  5  4  3  2 
7  bus blue c  2  NaN  NaN  NaN 
7  bus blue d  3  NaN  NaN  NaN 
8  walk red a  3  NaN  NaN  NaN 
8  walk red b  3  5  5  5 
8  walk red c  4  5  3  3 
8  walk red d  3  NaN  NaN  NaN 
9  car blue a  5  3  3  3 
9  car blue b  3  NaN  NaN  NaN 
9  car blue c  4  4  3  4 
9  car blue d  3  NaN  NaN  NaN 
+0

Хотя это гораздо более изящный/умный, чем мой. –

+0

И ПОЛНОМОЧИЙ! –

+0

@ AndyHayden: несколько недель назад я смотрел видео в первый раз, когда панда встретила своего ребенка с самого рождения, и это внезапно пришло ко мне. Помоги мне сделать это новым каноническим прилагательным, а? : ^) – DSM

3

Наивный способ бы написать вспомогательную функцию для извлечения соответствующего subDataFrames:

In [11]: def get_letter(df, letter): 
      res = df.loc[:, ['vehicle', 'color', letter] + [letter.upper() + str(i) for i in xrange(1, 4)]] 
      res.columns = ['vehicle', 'color', 'sl_val', 'BL_val1', 'BL_val2', 'BL_val3'] 
      res['sl'] = letter 
      return res 

In [12]: get_letter(df, 'a') 
Out[12]: 
    vehicle color sl_val BL_val1 BL_val2 BL_val3 sl 
resp              
1  bike green  5  3  4  5 a 
2  walk red  5  4  5  3 a 
3  car green  4  4  3  5 a 
4  car blue  4  NaN  NaN  NaN a 
5  bus black  2  NaN  NaN  NaN a 
6  car red  4  3  4  4 a 
7  bus blue  5  3  3  5 a 
8  walk red  3  NaN  NaN  NaN a 
9  car blue  5  3  3  3 a 

Тогда concating это получает результат вы после этого (возможно, с каким-то):

In [13]: pd.concat(get_letter(df, letter) for letter in 'abcd') 

In [14]: pd.concat(get_letter(df, letter) for letter in 'abcd').sort() 
Смежные вопросы