为 Pandas 数据框中的给定日期创建标志矩阵



我想在我的数据框中为选择性列的特定日期范围创建零。我无法找到任何有效的解决方案。

我的代码创建了一个 1 的矩阵,假设日期=1/10/2016 - 16/8/2018(即ytd(。matrix1cols=A,B,C,D:

df = pd.DataFrame(np.ones(shape=(len(dates), len(matrix1cols))), index=dates)
df.columns = ['A','B','C', 'D']

现在,我希望将 A 列 = 0 的 Q1(1 月至 3 月(日期、B = 0 的 Q2 日期、C = 0 的 Q3 日期和 col D = 0 的 Q4 日期,以 df 为单位。(我本质上是在为自己创建标志(

Ps-我的日期有很多年了,为了方便起见,我简化了数据集。

设置

dates = pd.date_range('2016/10/01', '2018/08/16', freq='M')
matrixcols = list('ABCD')
df = pd.DataFrame(np.ones((len(dates), len(matrixcols)), int), dates, matrixcols)
A  B  C  D
2016-10-31  1  1  1  1
2016-11-30  1  1  1  1
2016-12-31  1  1  1  1
2017-01-31  1  1  1  1
2017-02-28  1  1  1  1
2017-03-31  1  1  1  1
2017-04-30  1  1  1  1
2017-05-31  1  1  1  1
2017-06-30  1  1  1  1
2017-07-31  1  1  1  1
2017-08-31  1  1  1  1
2017-09-30  1  1  1  1
2017-10-31  1  1  1  1
2017-11-30  1  1  1  1
2017-12-31  1  1  1  1
2018-01-31  1  1  1  1
2018-02-28  1  1  1  1
2018-03-31  1  1  1  1
2018-04-30  1  1  1  1
2018-05-31  1  1  1  1
2018-06-30  1  1  1  1
2018-07-31  1  1  1  1

数字切片

创建一个自定义数组来定义放置零的位置

i = np.array([
#A  B  C  D
[1, 1, 0, 1],  # Q1 -> Only column C is zero
[1, 0, 0, 0],  # Q2 -> cols B, C, D are zero
[0, 0, 1, 1],  # Q3 -> cols A, B are zero
[0, 1, 1, 0],  # Q4 -> cols A, D are zero
])
q = df.index.quarter - 1
df * i[q]
A  B  C  D
2016-10-31  0  1  1  0
2016-11-30  0  1  1  0
2016-12-31  0  1  1  0
2017-01-31  1  1  0  1
2017-02-28  1  1  0  1
2017-03-31  1  1  0  1
2017-04-30  1  0  0  0
2017-05-31  1  0  0  0
2017-06-30  1  0  0  0
2017-07-31  0  0  1  1
2017-08-31  0  0  1  1
2017-09-30  0  0  1  1
2017-10-31  0  1  1  0
2017-11-30  0  1  1  0
2017-12-31  0  1  1  0
2018-01-31  1  1  0  1
2018-02-28  1  1  0  1
2018-03-31  1  1  0  1
2018-04-30  1  0  0  0
2018-05-31  1  0  0  0
2018-06-30  1  0  0  0
2018-07-31  0  0  1  1

另一种观点,看看它正在为正确的季度工作。

i = np.array([
#A  B  C  D
[1, 1, 0, 1],  # Q1 -> Only column C is zero
[1, 0, 0, 0],  # Q2 -> cols B, C, D are zero
[0, 0, 1, 1],  # Q3 -> cols A, B are zero
[0, 1, 1, 0],  # Q4 -> cols A, D are zero
])
q = df.index.quarter - 1
df.set_index(df.index.to_period('Q'), append=True).swaplevel(0, 1) * i[q]
A  B  C  D
2016Q4 2016-10-31  0  1  1  0
2016-11-30  0  1  1  0
2016-12-31  0  1  1  0
2017Q1 2017-01-31  1  1  0  1
2017-02-28  1  1  0  1
2017-03-31  1  1  0  1
2017Q2 2017-04-30  1  0  0  0
2017-05-31  1  0  0  0
2017-06-30  1  0  0  0
2017Q3 2017-07-31  0  0  1  1
2017-08-31  0  0  1  1
2017-09-30  0  0  1  1
2017Q4 2017-10-31  0  1  1  0
2017-11-30  0  1  1  0
2017-12-31  0  1  1  0
2018Q1 2018-01-31  1  1  0  1
2018-02-28  1  1  0  1
2018-03-31  1  1  0  1
2018Q2 2018-04-30  1  0  0  0
2018-05-31  1  0  0  0
2018-06-30  1  0  0  0
2018Q3 2018-07-31  0  0  1  1

一种解决方案是使用简单的for循环。作为第一步,请注意将您的索引转换为datetime,例如通过df.index = pd.to_datetime(df.index).

for q, col in enumerate(df, 1):
df.loc[df.index.quarter == q, col] = 0

同样,在这种情况下,但更详细:

for q, col in zip(range(1, 5), df):
df.loc[df.index.quarter == q, col] = 0

最新更新