首页 > 解决方案 > 遍历 DataFrame 的列并赋值

问题描述

我有一个按排序日期索引的单列 DataFrame(数据),我想创建一个带有 p 列的第二个 DataFrame,并为每一列分配一个移位版本的数据。即,我想在第一列data.shift(1)中看到,在第二列data.shift(2)中等等。我的实现如下:

lagged_data = pd.DataFrame(index = data.index, columns=[i+1 for i in range(p)])
for i in range(p):
    lagged_data.iloc[:,i] = data.shift(i+1)

然而,在执行之后,只有第一列被更新,而所有其他列仍然被 np.nan 填充。见下面的结果(p=3):

print(lagged_data.head())

           1   2    3
Date                 
gen-75   NaN NaN  NaN
feb-75  0.03 NaN  NaN
mar-75  0.04 NaN  NaN
apr-75 -0.04 NaN  NaN
mag-75  0.04 NaN  NaN

奇怪的是,通过再重复一次相同的循环,所有列都被正确填充。我真的看不出这种行为的原因,我也尝试通过这样做来创建副本

 lagged_data.iloc[:,i] = data.shift(i+1).copy()

但这给出了与以前相同的结果

标签: pythonpandasdataframe

解决方案


将系列分配给系列

您正在将数据框分配给系列。虽然这会产生结果,但您不应该期望它会起作用。相反,将一个系列分配给一个系列并使用pd.Series.shift

data = pd.DataFrame({'A': [1, 2, 3, 4, 5]})

lagged_data = pd.DataFrame(index=data.index, columns=[i+1 for i in range(3)])
for i in range(3):
    lagged_data.iloc[:,i] = data.iloc[:, 0].shift(i + 1)

print(lagged_data)

#      1    2    3
# 0  NaN  NaN  NaN
# 1  1.0  NaN  NaN
# 2  2.0  1.0  NaN
# 3  3.0  2.0  1.0
# 4  4.0  3.0  2.0

Noticedata是一个pd.DataFrame对象,whiledata.iloc[:, 0]是一个pd.Series对象。

pd.concat列表理解

在这种情况下,您可以pd.concat改为使用列表推导,指定keys参数和axis=1

res = pd.concat([data.iloc[:, 0].shift(i+1) for i in range(3)],
                keys=list(range(1, 4)), axis=1)

推荐阅读