Как разделить список словарей подряд на несколько строк фрейма данных pandas?

#python #pandas #dataframe

Вопрос:

У меня есть следующий фрейм данных:

             terms                                          periods
0      [741880, 3764106]            [{"name":"2010 год", "date":"31.12.2010", "value":"6621"},{"name":"2000 год", "date":"31.12.2000", "value":"17913"},{"name":"2006 год", "date":"31.12.2006", "value":"5849"},{"name":"2003 год", "date":"31.12.2003", "value":"9211"},{"name":"2012 год", "date":"31.12.2012", "value":"7647"},{"name":"2011 год", "date":"31.12.2011", "value":"8382"},{"name":"2014 год", "date":"31.12.2014", "value":"7388"},{"name":"2004 год", "date":"31.12.2004", "value":"8851"}]
 

Как вы можете видеть, в нем есть список словарей в строке.
Теперь я хочу что-то вроде:

 terms                                          date          value
0      [741880, 3764106]                     31.12.2010       6621
1      [741880, 3764106]                     31.12.2000       17913
2      [741880, 3764106]                     31.12.2006       5849

etc
 

Таким образом, список словарей должен быть разбит на строки в зависимости от количества элементов в списке.

Как я могу это сделать?

Комментарии:

1. Может быть, стоит посмотреть, как формируется этот фрейм данных, и применить необходимые преобразования к исходным данным?

2. исходные данные в формате json, и я сделал read_json, и это окончательный df

3. Ты пробовал pd.json_normalize ?

Ответ №1:

Попробуйте использовать apply() и explode() :

 df2 = (df['periods'].apply(lambda x: [[i['date'],i['value']] for i in x])
       .explode()
       .apply(pd.Series, index=['date','value'])])
df = pd.concat([df['terms'], df2, axis=1).reset_index(drop=True)
 

Выход:

 print(df)
              terms            date    value
  0     [741880, 3764106]   31.12.2010  6621
  1     [741880, 3764106]   31.12.2000  17913
  2     [741880, 3764106]   31.12.2006  5849
  3     [741880, 3764106]   31.12.2003  9211
  4     [741880, 3764106]   31.12.2012  7647
  5     [741880, 3764106]   31.12.2011  8382
  6     [741880, 3764106]   31.12.2014  7388
  7     [741880, 3764106]   31.12.2004  8851
 

Ответ №2:

Просто explode столбец periods и применитесь ps.Series к нему. Вы можете пропустить первые две строки, если данные в столбце periods уже являются списком словарей. Используйте установить индекс сброса, чтобы сохранить столбец терминов

 import ast
df['periods']=df['periods'].apply(ast.literal_eval)

df.set_index('terms').explode('periods').apply(lambda row: pd.Series(row['periods']), axis=1).reset_index()
 

выход:

                terms      name        date  value
0  [741880, 3764106]  2010 год  31.12.2010   6621
1  [741880, 3764106]  2000 год  31.12.2000  17913
2  [741880, 3764106]  2006 год  31.12.2006   5849
3  [741880, 3764106]  2003 год  31.12.2003   9211
4  [741880, 3764106]  2012 год  31.12.2012   7647
5  [741880, 3764106]  2011 год  31.12.2011   8382
6  [741880, 3764106]  2014 год  31.12.2014   7388
7  [741880, 3764106]  2004 год  31.12.2004   8851

 

Комментарии:

1. Получение этой ошибки: Ошибка значения: неправильный узел или строка:

2. Добавьте полную трассировку назад. Также добавьте вывод df.iloc[0,:].apply(type)

Ответ №3:

Попробуйте это:-

 periods = [{"name":"2010 год", "date":"31.12.2010", "value":"6621"},{"name":"2000 год", "date":"31.12.2000", "value":"17913"},{"name":"2006 год", "date":"31.12.2006", "value":"5849"},{"name":"2003 год", "date":"31.12.2003", "value":"9211"},{"name":"2012 год", "date":"31.12.2012", "value":"7647"},{"name":"2011 год", "date":"31.12.2011", "value":"8382"},{"name":"2014 год", "date":"31.12.2014", "value":"7388"},{"name":"2004 год", "date":"31.12.2004", "value":"8851"}]

print(f"{'Terms': <8}{'Name': <13}{'Date': <14}{'Value': <10}")
i = 0

for mem in periods:
    for rel in mem:
        print(f"{i: <8}{mem['name']:12}{mem['date']: <14}{mem['value']:6}")
        i  = 1
 

Выход:-

 Terms   Name         Date          Value     
0       2010 год    31.12.2010    6621  
1       2010 год    31.12.2010    6621  
2       2010 год    31.12.2010    6621  
3       2000 год    31.12.2000    17913 
4       2000 год    31.12.2000    17913 
5       2000 год    31.12.2000    17913 
6       2006 год    31.12.2006    5849  
7       2006 год    31.12.2006    5849  
8       2006 год    31.12.2006    5849   

etc.
 

Комментарии:

1. выполнение этого с помощью цикла for отнимает много времени

2. Сначала попробуйте, это не займет много времени!