如何从 Pandas 数据框中的大型每日 JSON 数据集计算平均月值?

时间:2020-12-21 06:15:45

标签: python json pandas dataframe datetime

我对使用 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}
等等许多日常价值。

我的目标是读取所有这些原始每日数据并计算“bpm”的月平均值并绘制到 matplot 图。我的问题是我在使用 Pandas datetime 或 mean() 操作时遇到问题,因为我认为 Pandas 并不像 datetime 中那样接受我的 dateTime 格式,当我尝试使用 mean() 时,它给了我一个 pandas.core.base.DataError: No numeric types to aggregate .

如何使用内置的 Pandas 工具通过将我的每日值按月份分组来计算月平均值?

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()

2 个答案:

答案 0 :(得分:2)

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 的数据。因此,如果 Month 的频率为“M”,请确保数据集中至少有 2 个月。

阅读 Pandas resample 文档了解更多详情。

答案 1 :(得分:0)

我没有您的数据,因此这可能无法立即生效。但除了你应该能够使用这个方法。

步骤

  1. value 列的 dict 值转换为列 (Reference)
  2. 分组依据 (Reference)
  3. 平均 (Reference)
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())