如何从 pandas 数据框中的大型每日 JSON 数据集计算平均月值?
Posted
技术标签:
【中文标题】如何从 pandas 数据框中的大型每日 JSON 数据集计算平均月值?【英文标题】:How can I compute average monthly value from large daily JSON dataset in pandas dataframe? 【发布时间】:2021-03-30 22:50:56 【问题描述】:我对使用 pandas 数据框读取数据比较陌生,并且在处理我的数据集时遇到了一些问题。我一直在阅读许多其他关于类似问题的 *** 帖子,但我一直无法将这些解决方案应用于我的案例,这可能是因为我的 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 格式,当我尝试使用 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()
【问题讨论】:
resample
解决了您的问题吗?
嗨,Prayson,不幸的是还没有。我试图应用您的建议,但 apply() 出现错误,并且我一直在获取列表索引必须。现在我得到 DataError raise DataError("No numeric types to aggregate") pandas.core.base.DataError: No numeric types to aggregate.
这意味着您没有要重新采样的数值。 df.dtypes
得到什么?
我的数据框值看起来像我的问题中显示的带有日期时间和值的示例。我想要的数值是 ['values']['bpm'] 值,但 df.dtypes 给我一个错误 TypeError: 'Series' object is not callable
如您所见,您拥有的是 Series 而不是 DataFrame。所以示例数据不一样。你可以试试df['value'].apply(pd.Series)
吗?这会扩大价值吗?
【参考方案1】:
将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 个月。
阅读Pandasresample
文档了解更多详情。
【讨论】:
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']
,您将看到图表。注意:我有更新数据来反映它【参考方案2】:
我没有您的数据,因此这可能无法立即生效。但除了你应该可以使用这个方法。
步骤
-
将
value
列的dict 值转换为列(Reference)
分组依据 (Reference)
平均 (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())
【讨论】:
我对print(df['bpm'].mean().sort_values())
这一行感到困惑,因为 df['bpm'].mean() 返回一个浮点值,所以这段代码会抛出错误 AttributeError: 'numpy.float64' object has no attribute 'sort_values'
你的意思是在一个列然后排序?以上是关于如何从 pandas 数据框中的大型每日 JSON 数据集计算平均月值?的主要内容,如果未能解决你的问题,请参考以下文章
将 JSON 时间戳字符串转换为 pandas 数据框中的 python 日期