2015-07-21 3 views
1

Совсем аналогичный вопрос был задан there, и он был блестяще ответил пользователем1609452 в R. Тем не менее, это была конкретная проблема. Я хотел бы расширить вопрос. давайте возьмем почти ту же таблицу (MyData):pandas df in inested json

ID Location L_size L_color Station S_size S_color  Category C_size C_color 
1  Alpha  6  #000000  Zeta  3  #333333  Big  0.63  #306100 
2  Alpha  6  #000000  Zeta  3  #333333  Medium  0.43  #458b00 
3  Alpha  6  #000000  Zeta  3  #333333  small  0.47  #6aa232 
4  Alpha  6  #000000  Yota  3  #4c4c4c  Big  0.85  #306100 
5  Alpha  6  #000000  Yota  3  #4c4c4c  Medium  0.19  #458b00 
6  Alpha  6  #000000  Yota  3  #4c4c4c  small  0.89  #6aa232 
7  Beta  6  #191919  Theta  4  #666666  Big  0.09  #306100 
8  Beta  6  #191919  Theta  4  #666666  Medium  0.33  #458b00 
9  Beta  6  #191919  Theta  4  #666666  small  0.79  #6aa232 
10  Beta  6  #191919  Theta  4  #666666  Big  0.89  #306100 
11  Beta  6  #191919  Meta  3  #7f7f7f  Medium  0.71  #458b00 
12  Beta  6  #191919  Meta  3  #7f7f7f  small  0.59  #6aa232 

Каждая категория имеет один или несколько атрибутов (здесь только один: размер). То, что я хотел, это чтобы сообщить размер для каждого из родителей/детей в файле JSon:

 { 
"name":"MyData", 
"size":12, 
"color":"#ffffff" 
"children":[ 
    { 
    "name":"Alpha", 
    "size":6, 
    "color":"#000000" 
    "children":[ 
     { 
      "name":"Zeta", 
      "size":3, 
      "color":"#333333" 
      "children":[ 
       { 
       "name":"Big", 
       "size":0.63, 
       "color":"#306100" 
       }, 
... 

и т.д. я не мог сделать это в R, ни в панд ... Любая идея?

EDIT: Моя цель - связать разнообразную информацию с детьми, а не только размер. Я добавил колонку цветов для каждого основного столбца. Мой исходный фреймворк большой и содержит много информации, но я не могу вставить его здесь, ради ясности.

ВТОРОЙ РЕДАКТИРОВКА: Ответ на chrisb Он почти сработал! Отличное обновление. Тем не менее json-файл неправильно загружен в файл javascript. Файл, кажется, с ног на голову (MYDATA в конце), а также информацию от родителя до и после того, как дети информации:

{ 
    "children":[ 
     { 
     "color":"#000000", 
     "children":[ 
      { 
       "color":"#4c4c4c", 
       "children":{ 
        "color":"#306100", 
        "name":"Big", 
        "size":0.85 
       }, 
       "name":"Yota", 
       "size":3 
      }, 
      { 
       "color":"#333333", 
       "children":{ 
        "color":"#306100", 
        "name":"Big", 
        "size":0.63 
       }, 
       "name":"Zeta", 
       "size":3 
      } 
     ], 
     "name":"Alpha", 
     "size":6 
     }, 
     { 
     "color":"#191919", 
     "children":[ 
      { 
       "color":"#7f7f7f", 
       "children":{ 
        "color":"#458b00", 
        "name":"Medium", 
        "size":0.71 
       }, 
       "name":"Meta", 
       "size":3 
      }, 
      { 
       "color":"#666666", 
       "children":{ 
        "color":"#306100", 
        "name":"Big", 
        "size":0.09 
       }, 
       "name":"Theta", 
       "size":4 
      } 
     ], 
     "name":"Beta", 
     "size":6 
     } 
    ], 
    "name":"MyData", 
    "size":12 

Последнее редактирование: Работает отлично. Крис снял последнюю часть сценария, который он написал, когда он обновил его, так что вот оно. Спасибо Крису!

data = {'name': 'MyData', 
     'size': len(MyData), 
     'children': make_children(MyData, levels)} 

print json.dumps(data) 

ответ

2

Во-первых, вам нужно какое-то отображение того, что составляет каждый уровень. Я использую кортежи столбца, который определяет "name" и префикс других атрибутов, которые вы хотите с этого уровня, например.

levels = [('Location', 'L_'), 
      ('Station', 'S_'), 
      ('Category', 'C_')] 

Затем это похоже рекурсивная функция, только теперь дополнительные столбцы быть подобраны в каждом шаге (нахождение столбцов, которые начинаются с префикса) и добавляется к дереву сжать их в столбцы/значения. Там есть возможность убрать это, но по крайней мере дать идею.

def make_children(df, levels): 
    if len(levels) == 1: 
     name, prefix = levels[0] 
     level_cols = [name] + [c for c in df if c.startswith(prefix)] 
     df = df[level_cols] 
     key_names = ['name'] + [c.strip(prefix) for c in level_cols[1:]] 
     return dict(zip(key_names, df.values[0])) 
    else: 
     h, tail = levels[0], levels[1:] 
     name, prefix = h 
     level_cols = [name] + [c for c in df if c.startswith(prefix)] 

     data = [] 
     for keys, df_gb in df.groupby(level_cols): 
      key_names = ['name'] + [c.strip(prefix) for c in level_cols[1:]] 
      d = dict(zip(key_names, keys)) 
      d['children'] = make_children(df_gb, tail) 
      data.append(d) 
     return data  
+0

Thanks Chris. Вы нашли хороший способ избежать сценария R из приведенной выше ссылки. Мой пример не был достаточно хорош, так как ваш скрипт ловко взял размер от длины df. Я хотел иметь больше, чем просто размер ... Я отредактирую вопрос ... – Sara

+0

Крис, я думаю, мы добираемся туда, но пока json действителен, он не загружается должным образом моим javascript. Посмотрите мое второе обновление. благодаря! – Sara

+0

@Sara - JSON неупорядочен, так что это не проблема. Но все должно быть струнами. Попробуйте выполнить 'df = df.astype (str)' перед преобразованием в dict/JSON. – chrisb