我有2个时间序列的数据帧。两者都只包含值[0,1]。第一个称为init_signal
,第二个称为end_signal
。这个想法是在init_signal
有一个1
时创建一个新的数据帧,它将在end_signal
中找到NEXT 1。
下面的示例将init_signal和end_signal合并为一个数据帧。第一列是init_signal,第二列是end_signal。
例如:
2016-06-13 1 0
2016-06-14 0 0
2016-06-15 0 1
2016-06-16 0 0
将成为:
2016-06-13 1
2016-06-14 1
2016-06-15 1
2016-06-16 0
例如2:
2016-06-13 1 1
2016-06-14 0 0
2016-06-15 0 1
2016-06-16 0 0
将成为:
2016-06-13 1
2016-06-14 1
2016-06-15 1
2016-06-16 0
在第二个示例中,如果在与init_signal相同的行中也有一个1,它将被忽略。
我一直在使用复杂的循环。有非循环方式吗?
答案 0 :(得分:3)
我希望这会有所帮助并涵盖所有边界条件。
onChange
输出:
import pandas as pd
import datetime as dt
# Dummy data
df = pd.DataFrame()
df['init_signal'] = [0,0,0,1,0,0,0,0,1,0,0,0,0,0,0,0,1,0,0]
df['end_signal'] = [0,1,0,0,0,0,1,0,1,0,0,1,0,1,0,0,0,1,0]
df.index = [dt.date.today()+dt.timedelta(-i) for i in reversed(range(len(df)))]
# Cumsum for calculation
df['init_c'] = df['init_signal'].cumsum()
df['end_c'] = df['end_signal'].cumsum()
# result calculation
func = lambda x: (x==x.min()).shift().fillna(True)
df['result'] = df.groupby('init_c')['end_c'].transform(func)
df['result'] = df['result']&df['init_c'].astype(bool)
df['result'] = df['result'].astype(int)
# dropping temp columns
df.drop(['init_c','end_c'], axis=1, inplace=True)
print(df)
答案 1 :(得分:0)
让我们尝试一下:
df1 = df.assign(end_signal = df['end_signal'].where(df['init_signal'].values != 1, 0))
df1 = df1.set_index('time')
(df1['init_signal'] + df1['end_signal'].shift().bfill()*-1).cumsum()
输出:
time 0
0 2016-06-13 1.0
1 2016-06-14 1.0
2 2016-06-15 1.0
3 2016-06-16 0.0
答案 2 :(得分:0)
这可以通过三个步骤和0个循环来实现:
init_signal
和end_signal
创建单个列。
(两者的记录默认都仅是启动信号。)注意:我不确定一开始如何处理案件。我假设在init_signal
之前总是 一个end_signal
。如果不是这样,则需要为此构建一个处理程序,但这将是这些步骤结束时的简单条件。
在这一步中,我们创建一个只有几天的地方,其中有init_signal
和end_signal
。
import numpy as np
df['result'] = np.nan
#Add end dates
mask = (df['end_signal'] == 1)
df.loc[mask,'result'] = 0
#Add init_signals.
#Note: This will overwrite days that already have an end_signal
mask = (df['init_signal'] == 1)
df.loc[mask,'result'] = 1
这将获取na值,并将其替换为最近发生的状态。
df.fillna(method='ffill',inplace=True)
在定义中,我们说带有end_signal
的日期应为1,因此我们需要将其添加回数据框。
mask = (df['end_signal'] == 1)
df.loc[mask,'result'] = 1
答案 3 :(得分:-1)
我认为没有一种非循环的方式可以合并您想要的逻辑(如果有的话,它不比循环简单)。见下文...
df['status'] = 0
for i in df.index:
if df.xs(i)['init_signal'] == 1:
df.at[i,'status'] = 1
elif i != 0 and df.xs(i-1)['status'] == 1 and df.xs(i)['end_signal'] != 1:
df.at[i,'status'] = 1
else:
df.at[i,'status'] = 0
这将创建一个“状态”列,该列将一直为零,直到init_signal设置为“ on”为止,并且在init_signal也不等于1的一天(根据您的示例2)将保持为“ on”状态,直到end_signal = 1为止。当连续给出多个结束/初始化信号时,其他非循环解决方案似乎也会遇到麻烦。