#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. Сначала попробуйте, это не займет много времени!