我在标题中加上了分贝,但是我不确定那是我的意思。这是问题的完整说明。我有一个数据框,其中包含来自多个主题的数据。我要做的是分析相隔X天的数据。我的想法是,我只想考虑每天(例如,第4天)从某个主题收集的数据。这里要注意的是,是针对受试者并行收集数据的,所以我不能只是每隔4天就对受试者进行一次采集,而是需要对每个受试者进行抽取/下采样/任何操作。数据框中的两个关键列是“主题”和“ session_timestamp”。在后者中,日期和时间的格式如下例所示:2017-11-10 16:30:47。有没有一种好的方法可以在python中完成此操作?
编辑: 第一批评论者要求提供带有一些示例数据的数据框的更具体示例。这是一个玩具数据框,与我的玩具数据框相似,应该很容易使用。下面的代码创建一个包含4列的数据框:subjectID,日期,score1和score2。请注意,一个对象在给定日期可以有一个以上的条目(基本上,这是神经记录,数据框的每一行代表一个神经元,我们每个对象可以记录一个以上的神经元)
import pandas as pd
import numpy as np
ab = pd.DataFrame()
ab["subjectID"] = np.random.randint(5, size=200)#random list of "subjects" from 0 to 4
ab["date"] = np.random.randint(20, size=200)#random list of "dates" from 0 to 19
ab["score1"] = np.random.randint(200, size=200)#meant to simulate one measurement from one subject
ab["score2"] = np.random.randint(400, size=200)#meant to simulate a second measurement
我想要做的是过滤每个主题至少相隔4天收集的数据(分数1和得分2)。该代码可能非常简单,并且需要受试者输入条目的第一天,然后再输入第4天。但是更好的解决方案是,第一天,然后是超过3天的第二天,然后是超过3天的第二天(并非每个受试者每天都有样本,因此严格地“每4天天”代码不会那么优雅)。应包括在允许的日期收集的所有数据。例如,应包括日期代码为0(如果是该对象的第一天)的所有数据。
答案 0 :(得分:0)
我相信您可能正在寻找一种对培训样本进行总体抽样的方法。为此,您可能需要使用某些不平衡学习方法,例如:ADASYN,SMOTE,Tomek链接。随机子采样/过度采样等。(Oversampling and undersampling in data analysis上的维基百科文章提供了不错的概述)。 imbalanced-learn软件包中有一个便捷的实现。
答案 1 :(得分:0)
首先创建一个数据框(包含随机数据):
import pandas as pd
import numpy as np
from datetime import datetime, timedelta
ab = pd.DataFrame()
ab["subjectID"] = np.random.randint(5, size=200)#random list of "subjects" from 0 to 4
ab["day_number"] = np.random.randint(50, size=200)#random list of "dates" from 0 to 50
ab['real_date'] = ab.day_number.apply(lambda d: datetime(2018, 1, 1) + timedelta(days=d)) #to simulate real dates
ab["score1"] = np.random.randint(200, size=200)#meant to simulate one measurement from one subject
ab["score2"] = np.random.randint(400, size=200)#meant to simulate a second measurement
min_day = ab.real_date.min()
ab = ab.groupby(['subjectID', 'real_date']).sum() #because some subjects have more than 1 score each day
print(ab.head(10))
day_number score1 score2
subjectID real_date
0 2018-01-01 0 306 273
2018-01-04 3 32 60
2018-01-05 4 61 135
2018-01-08 21 477 393
2018-01-09 8 22 341
2018-01-10 9 137 30
2018-01-11 30 281 674
2018-01-14 13 183 396
2018-01-15 14 41 337
2018-01-16 15 83 50
然后用下一个现有日期的数据填充没有数据的日期:
df = ab.reset_index(level='subjectID').groupby('subjectID').resample('D').mean() #Complete missing dates with NaN
df = df.drop(columns='subjectID')
df = df.groupby(level='subjectID').fillna(method='bfill') #fills the NaN with the first next non NaN value
df = df.apply(pd.to_numeric, downcast='integer') #just to have ints, easier to read
print(df.head(10))
day_number score1 score2
subjectID real_date
0 2018-01-01 0 306 273
2018-01-02 3 32 60
2018-01-03 3 32 60
2018-01-04 3 32 60
2018-01-05 4 61 135
2018-01-06 21 477 393
2018-01-07 21 477 393
2018-01-08 21 477 393
2018-01-09 8 22 341
2018-01-10 9 137 30
接下来的4天重采样(分组):
res = df.reset_index(level='subjectID').groupby('subjectID').resample('4D').first() #group by 4 days periods and keep only the first value
res = res.drop(columns='subjectID')
print(res.head(10))
day_number score1 score2
subjectID real_date
0 2018-01-01 0 306 273
2018-01-05 4 61 135
2018-01-09 8 22 341
2018-01-13 13 183 396
2018-01-17 18 91 46
2018-01-21 20 76 333
2018-01-25 48 131 212
2018-01-29 29 92 81
2018-02-02 32 172 55
2018-02-06 72 98 246
最后重置索引,并在超过4天没有数据的情况下处理该情况:
res = res.reset_index('real_date', drop=True) #the real_date has no meaning anymore
res['real_date'] = res.day_number.apply(lambda d: min_day + timedelta(days=d)) #good real_date based on the day_number
res = res.drop(columns='day_number')
res = res.set_index('real_date', append=True)
res = res.groupby(level=['subjectID', 'real_date']).first() #regroups periods with no data for more than 4 days
print(res.head(10))
score1 score2
subjectID real_date
0 2018-01-01 306 273
2018-01-05 61 135
2018-01-09 22 341
2018-01-14 183 396
2018-01-19 91 46
2018-01-21 76 333
2018-01-30 92 81
2018-02-02 172 55
2018-02-10 40 218
2018-02-15 110 112
这有点复杂,但是我认为这是最好的方法。虽然我不知道效率,但是看起来还不错。