Я относительно новичок в работе с фреймами данных pandas для чтения данных, и у меня возникли проблемы с работой с моим набором данных. Я читал много других сообщений StackOverflow по аналогичной проблеме, но у меня возникли проблемы с применением этих решений в моем случае, возможно, из-за структуры моих данных JSON. Мои данные JSON, расположенные в моем фрейме данных df = pd.DataFrame.from_records(data)
, обычно выглядят так:
dateTime value
0 01/16/20 04:32:42 {'bpm': 70, 'confidence': 0}
1 01/16/20 04:32:57 {'bpm': 70, 'confidence': 0}
2 01/16/20 04:33:12 {'bpm': 70, 'confidence': 1}
Моя цель — прочитать все эти необработанные ежедневные данные, вычислить среднемесячное значение «ударов в минуту» и построить график на матплоте. Моя проблема в том, что у меня проблемы с использованием операций pandas datetime или mean(), потому что я не думаю, что pandas принимает мой формат dateTime как на самом деле в datetime, и когда я пытаюсь использовать mean(), это дает мне ошибку pandas.core.base.DataError: No numeric types to aggregate
.
Как я могу использовать встроенные инструменты панд, чтобы позволить мне вычислить среднемесячное значение, сгруппировав мои ежедневные значения вместе в зависимости от месяца?
for file in os.listdir(data_dir): # look at every file in the folder
if file.startswith("heart_rate") and file.endswith(".json"): # only want heart_rate-date.json files
with open(os.path.join(data_dir, file)) as f: # open each file in data_dir
data = json.load(f)
df = pd.DataFrame.from_records(data)
print(df)
#df.dateTime = pd.to_datetime(df.dateTime)
#df['Month'] = df['dateTime'].dt.month
for i, j in enumerate(data):
if data[i]['value']['confidence'] > 0:
daily_avg_bpm += data[i]['value']['bpm']
daily_date = data[i]['dateTime'].split()[0]
my_date = datetime.datetime.strptime(daily_date, "%m/%d/%y").date()
days.append(my_date)
months.append(daily_date[:2])
daily_avg_bpm /= len(data)
dates.append(daily_date)
avg_bpms.append(round(daily_avg_bpm))
f.close()
plt.xlabel('Month')
plt.ylabel('Heart Rate')
plt.title("Fitbit Heart Rate")
for i, j in enumerate(dates):
plt.plot(dates[i], avg_bpms[i])
plt.show()
Привет, Прейсон. К сожалению, еще нет. Я пытался применить ваше предложение, но у меня были ошибки с apply(), и я получал обязательные индексы списка. Теперь я получаю DataError поднять DataError («Нет числовых типов для агрегирования») pandas.core.base.DataError: Нет числовых типов для агрегирования.
Это означает, что у вас нет числовых значений для повторной выборки. Что вы получаете df.dtypes
?
Значения моего фрейма данных выглядят как пример, показанный в моем вопросе, с датой и временем. Числовые значения, которые я хочу, представляют собой значения ['values']['bpm'], но df.dtypes дает мне ошибку TypeError: объект 'Series' не вызывается
Как видите, у вас Series, а не DataFrame. Таким образом, данные примера не совпадают. Можете попробовать df['value'].apply(pd.Series)
? Это расширяет ценность?
У меня нет ваших данных, поэтому это может не сработать сразу. Но кроме этого вы должны уметь пользоваться этим методом.
Шаги
value
в столбцы (Справочник)import pandas as pd
df = pd.DataFrame.from_records(data)
# Step 1
df = pd.concat([df.drop(['value'], axis=1), df['value'].apply(pd.Series)], axis=1)
# Step 2
df.groupby(by=[df.dateTime])
# Step 3
print(df['bpm'].mean().sort_values())
Я запутался в строке print(df['bpm'].mean().sort_values())
, потому что df['bpm'].mean() возвращает значение с плавающей запятой, поэтому этот код выдает ошибку AttributeError: 'numpy.float64' object has no attribute 'sort_values'
Вы имеете в виду собрать эти значения в столбец, а затем отсортировать?
Самый простой способ преобразовать ваши values
в столбцы и преобразовать dateTime
в фактическую дату и время. При этом вы можете использовать resample
для агрегирования по желанию частоты:
import pandas as pd
data = pd.DataFrame({'dateTime':[ '01/16/20 04:32:42', '01/16/20 04:32:57', '02/16/20 04:33:12', '03/16/20 04:33:12'],
'value': [{'bpm': 70, 'confidence': 0}, {'bpm': 75, 'confidence': 0},
{'bpm': 73, 'confidence': 1}, {'bpm': 78, 'confidence': 1}]})
# expland
df = data['value'].apply(pd.Series)
# to datetime and set index
df['dateTime'] = pd.to_datetime(data['dateTime'])
df.set_index('dateTime', inplace=True)
# data resample to Monthy with mean
example = df.resample('M', kind='period').mean()
# plot
example['bpm'].plot(title = "Fitbit Heart Rate", xlabel = "Month", ylabel = "Heart Rate");
Чтобы график отображался, убедитесь, что у вас есть данные с N > 1 для выбранной частоты. Поэтому, если частота «M» для месяца, убедитесь, что в наборе данных есть как минимум 2 месяца.
Read Pandas resample documentation for more details.UserWarning: Attempting to set identical left == right == 600.0 results in singular transformations; automatically expanding. ax.set_xlim(left, right)
и ничего не показывает.
Это потому, что у нас есть данные только за один месяц. Так что ничего не увидишь. измените дату выше на ['01/16/20 04:32:42', '01/16/20 04:32:57', '02/16/20 04:33:12']
, и вы увидите график. Примечание. У меня есть данные обновления, чтобы отразить это.
resample
решил вашу проблему?