您好我有以下格式的数据集:
复制数据的代码:
import pandas as pd
d1 = {'Year':
['2008','2008','2008','2008','2008','2008','2008','2008','2008','2008'],
'Month':['1','1','2','6','7','8','8','11','12','12'],
'Day':['6','22','6','18','3','10','14','6','16','24'],
'Subject_A':['','30','','','','35','','','',''],
'Subject_B':['','','','','','','','40','',''],
'Subject_C': ['','','','','','65','','50','','']}
d1 = pd.DataFrame(d1)
我将数字输入为字符串以显示空白单元格
前三列表示日期(年,月和日),以下列表示个人(我的实际数据文件包含约300个此类行和约1000个主题。我在此处提供了数据的子集)。
如果列值是指快速消费品产品的支出。 我想做的是以下几点:
第1部分(开始和结束点)
a)对于每个人,找到第一个观察并复制至少前六个月的第一个观察值。例如:主题C的第一次观察发生在2008年8月10日。在这种情况下,我希望2008年6月10日的所有行等于主题C的65(大约2/12/2008) 是截止日期。因此,对于Subject_C的列空白,我们将第3个单元格从顶部离开。
b)找到最后一次观察并重复最后一次观察,接下来的3个月。例如,对于Subject_A,我们重复35次(直到2008年11月6日)。
请参阅下图,了解带有解决方案的突出显示的单元格。
第二部分 - (两者之间的行)
接下来我想做两件事(我需要分别做以下三个步骤,而不是一次完成):
对于像Subject_A这样的人,找到两个一个接一个的观察结果(30和35)。
i)使用两次观察的平均值。在这种情况下,我们在四行中将有32.5而不关心时间。
例如:
ii)找出两次观察之间的总时间并取平均时间。在时间段的前半部分分配第一个值,而在下半部分分配第二个值。例如 - 对于主题1,在01/22/208和08/10/2008之间的总天数是201天。对于前201/2 = 100.5天,将值30分配给Subject_A,并将剩余值赋值为35.在这种情况下,Subject_A和Subject_C的列将如下所示:
最终数据集将使用(a),(b)& (i)或(a),(b)& (ⅱ)
最终数据I [使用a,b和i]
最终数据II [使用a,b和ii]
我将不胜感激任何帮助。提前致谢。如果步骤不清楚,请告诉我。
跟进问题和问题
感谢@Juan的初步答复。这是我的后续问题。假设Subject_A有超过2个观察值(下面的示例数据的代码)。我们能否扩展此代码以包含2个以上的观察结果?
import pandas as pd
d1 = {'Year':
['2008','2008','2008','2008','2008','2008','2008','2008','2008','2008'],
'Month':['1','1','2','6','7','8','8','11','12','12'],
'Day':['6','22','6','18','3','10','14','6','16','24'],
'Subject_A':['','30','','45','','35','','','',''],
'Subject_B':['','','','','','','','40','',''],
'Subject_C': ['','','','','','65','','50','','']}
d1 = pd.DataFrame(d1)
问题 对于当前的代码,我发现了第二部分(ii)的问题。这是我得到的输出:
这实际上是在正确的轨道上。 35以上的两个单元格似乎没有更新。我的结局有什么问题吗?同样的问题也是如此,我们能够将它扩展到> 2次观察的情况吗?
答案 0 :(得分:1)
这里是主题A的代码解决方案。应该与其他主题一起使用:
d1 = {'Year':
['2008','2008','2008','2008','2008','2008','2008','2008','2008','2008'],
'Month':['1','1','2','6','7','8','8','11','12','12'],
'Day':['6','22','6','18','3','10','14','6','16','24'],
'Subject_A':['','30','','45','','35','','','',''],
'Subject_B':['','','','','','','','40','',''],
'Subject_C': ['','','','','','65','','50','','']}
d1 = pd.DataFrame(d1)
d1 = pd.DataFrame(d1)
## Create a variable named date
d1['date']= pd.to_datetime(d1['Year']+'/'+d1['Month']+'/'+d1['Day'])
# convert to float, to calculate mean
d1['Subject_A'] = d1['Subject_A'].replace('',np.nan).astype(float)
# index of the not null rows
subja = d1['Subject_A'].notnull()
### max and min index row with notnull value
max_id_subja = d1.loc[subja,'date'].idxmax()
min_id_subja = d1.loc[subja,'date'].idxmin()
### max and min date for Sub A with notnull value
max_date_subja = d1.loc[subja,'date'].max()
min_date_subja = d1.loc[subja,'date'].min()
### value for max and min date
max_val_subja = d1.loc[max_id_subja,'Subject_A']
min_val_subja = d1.loc[min_id_subja,'Subject_A']
#### Cutoffs
min_cutoff = min_date_subja-pd.Timedelta(6, unit='M')
max_cutoff = max_date_subja+pd.Timedelta(3, unit='M')
## PART I.a
d1.loc[(d1['date']<min_date_subja) & (d1['date']>min_cutoff),'Subject_A'] = min_val_subja
## PART I.b
d1.loc[(d1['date']>max_date_subja) & (d1['date']<max_cutoff),'Subject_A'] = max_val_subja
## PART II
d1_2i = d1.copy()
d1_2ii = d1.copy()
lower_date = min_date_subja
lower_val = min_val_subja.copy()
next_dates_index = d1_2i.loc[(d1['date']>min_date_subja) & subja].index
for N in next_dates_index:
next_date = d1_2i.loc[N,'date']
next_val = d1_2i.loc[N,'Subject_A']
#PART II.i
d1_2i.loc[(d1['date']>lower_date) & (d1['date']<next_date),'Subject_A'] = np.mean([lower_val,next_val])
#PART II.ii
mean_time_a = pd.Timedelta((next_date-lower_date).days/2, unit='d')
d1_2ii.loc[(d1['date']>lower_date) & (d1['date']<=lower_date+mean_time_a),'Subject_A'] = lower_val
d1_2ii.loc[(d1['date']>lower_date+mean_time_a) & (d1['date']<=next_date),'Subject_A'] = next_val
lower_date = next_date
lower_val = next_val
print(d1_2i)
print(d1_2ii)