做宏观经济研究,做数据清洗是第一步。现在通过AI辅助编程,可以为我们提供一些便利,本文梳理两个案例。
一、填充春节缺失值
因为春节,很多经济数据往往只公布1-2月合并数据,这有时会造成2月单月数据缺失,比如下图中的制造业增加值同比,需要手动将1-2月累计同比,复制到2月当月同比。我们尝试通过AI编程实现。
向AI描述我们的需求
我有一个2列的DataFrame数据,index是月份,格式是yyyy-mm,第1列数据的部分数据缺失,我希望把第1列的数据补全,补全的数据是第2列的对应数据,请用Python实现
以下是AI给的程序,还附带了说明
好的,您可以使用`fillna`方法来实现将第一列的缺失值填充为第二列对应的值。具体代码如下:
import pandas as pd
# 读取数据
df = pd.read_csv('your_file.csv', index_col=0)
# 使用第二列的数据填充第一列的缺失值
df.iloc[:, 0] = df.iloc[:, 0].fillna(df.iloc[:, 1])
# 输出结果
print(df)
其中,your_file.csv是您的数据文件名。这段代码会读取该文件,并将第一列的缺失值填充为第二列对应的值。最后输出结果。
AI给的这段代码的核心,是使用.fillna()来填充缺失值,能否成功呢?我们来实验一下,
缺失值填充前
缺失值填充后
从结果上可以看到,2022年2月和2023年2月,两个单月缺失值,都使用累计值做了填充,实现了我们的需求。
补齐1月日期,用2月数据填充
我有一个DataFrame数据,index是月份,格式是yyyy-mm,其中,1月的index缺失,需要补全所有的月份,并用缺失值的后一个观测值,填充缺失值,请用Python实现
好的,您可以使用resample方法和fillna方法来实现将缺失值填充为后一个观测值,并补全所有的月份。具体代码如下:
import pandas as pd
# 读取数据
df = pd.read_csv('your_file.csv', index_col=0)
# 将index转换为DatetimeIndex对象
df.index = pd.to_datetime(df.index)
# 重新采样,以补全所有的月份
df_resampled = df.resample('M').asfreq()
# 使用后一个观测值填充缺失值
df_filled = df_resampled.fillna(method='bfill')
# 输出结果
print(df_filled)
其中,your_file.csv是您的数据文件名。这段代码会读取该文件,并将index转换为DatetimeIndex对象。然后使用resample方法重新采样,以补全所有的月份。接着使用fillna方法将缺失值填充为后一个观测值。最后输出结果
缺失值填充前
缺失值填充后
从结果上看,右侧缺失值填充后,一方面填充了2022年2月和2023年2月的缺失值,也补充了2022年1月和2023年1月的index缺失,所以多了两行,很好的满足了我们的需求,而且代码很简洁。
二、根据同比调整绝对值序列
我们知道,由于统计样本的差异,我们使用官方发布的绝对值计算的同比,有时与官方发布的同比,并不匹配,比较典型的比如固定资产投资额的累计值自算同比,与官方发布的累计同比,存在较大差异。这种情况,我们如果想计算单月同比,则需要根据官方同比,选定一个基期,折算一个绝对值序列。
首先,填充缺失值,以2月累计同比填充1月缺失值,以2月累计值的一半填充1月缺失值
我有一个DataFrame数据,index是月份,格式是yyyy-mm,其中,1月的index缺失,我需要补全所有的月份,其中,第1列的缺失值用后一个观测值的一半填充,第2列的缺失值用后一个观测值填充,请用Python实现
好的,您可以使用resample方法和fillna方法来实现将缺失值填充为后一个观测值,并补全所有的月份。对于第1列的缺失值,您可以使用fillna方法和bfill方法来实现将缺失值填充为后一个观测值的一半。具体代码如下:
import pandas as pd
# 读取数据
df = pd.read_csv('your_file.csv', index_col=0)
# 将index转换为DatetimeIndex对象
df.index = pd.to_datetime(df.index)
# 重新采样,以补全所有的月份
df_resampled = df.resample('M').asfreq()
# 使用后一个观测值填充第2列的缺失值
df_resampled.iloc[:, 1] = df_resampled.iloc[:, 1].fillna(method='bfill')
# 使用后一个观测值的一半填充第1列的缺失值
df_resampled.iloc[:, 0] = df_resampled.iloc[:, 0].fillna(df_resampled.iloc[:, 0].shift(1) / 2)
# 输出结果
print(df_resampled)
其中,your_file.csv是您的数据文件名。这段代码会读取该文件,并将index转换为DatetimeIndex对象。然后使用resample方法重新采样,以补全所有的月份。接着使用fillna方法将第2列的缺失值填充为后一个观测值,将第1列的缺失值填充为后一个观测值的一半。最后输出结果。
我们来实验一下,
缺失值填充前
缺失值填充后
从结果上可以看到,1月缺失的时间序列填充了,1月的累计同比缺失值用2月数据填充了,但是1月的累计值缺失值出现了错误,使用的是12月的值的一半。这是因为我们把数据按照时间进行了逆序排列,正常情况下是不需要修改的。
那么我们把上述程序中的df.iloc[:, 0].shift(1)改成df.iloc[:, 0].shift(-1),改完之后再跑一下,结果就没问题了。
缺失值填充前
缺失值填充后
然后,选定基期来生成绝对值序列
我现在有一个dataframe数据,时间index是月度数据,时间格式是xxxx-xx,第1列是数值,第2列是同比,我需要以某一年为基期,通过同比数据向前和向后外推出其他值,基期使用参数设定,请用Python实现
import pandas as pd
def extrapolate_data(df, base_year, base_month):
# 将时间字符串转换为pandas的时间戳
df.index = pd.to_datetime(df.index, format="%Y-%m")
# 获取基准年月的时间戳
base_date = pd.Timestamp(year=base_year, month=base_month, day=1)
# 向前推算
current_date = base_date - pd.DateOffset(months=1)
while current_date in df.index:
df.loc[current_date, '第1列'] = df.loc[current_date + pd.DateOffset(months=1), '第1列'] / (1 + df.loc[current_date, '第2列'] / 100)
current_date -= pd.DateOffset(months=1)
# 向后推算
current_date = base_date + pd.DateOffset(months=1)
while current_date in df.index:
df.loc[current_date, '第1列'] = df.loc[current_date - pd.DateOffset(months=1), '第1列'] * (1 + df.loc[current_date, '第2列'] / 100)
current_date += pd.DateOffset(months=1)
return df
# 示例数据
data = {'时间': ['2020-12', '2021-01', '2021-02', '2021-03'],
'第1列': [None, 100, None, None],
'第2列': [0.03, 0.02, 0.05, -0.02]}
df = pd.DataFrame(data)
df.set_index('时间', inplace=True)
# 设置基准年月
base_year = 2021
base_month = 1
# 计算结果
result = extrapolate_data(df, base_year, base_month)
print(result)
我们仔细读程序,我们发现,因为我们给出的是12个月的同比来生成绝对值,AI可能习惯的是根据环比来生成,所以AI给的程序,时间间隔是1个月,我们需要手动调整一下,比如,向后推算的时候:
current_date = base_date + pd.DateOffset(months=1)要改成current_date = base_date + pd.DateOffset(months=12)
另外,因为我们的列名是不固定的,所以需要使用.iloc来定位,而不是.loc,所以
df.loc[current_date, '第1列'] = df.loc[current_date - pd.DateOffset(months=1), '第1列'] * (1 + df.loc[current_date, '第2列'] / 100)要改成
df.loc[current_date].iloc[0] = df.loc[[current_date + pd.DateOffset(months=12)]].iloc[0, 0] / (1 + df.loc[[current_date + pd.DateOffset(months=12)]].iloc[0, 1] / 100)
我们跑了一下程序,发现结果没有出来,我们检查了一下,发现是base_date = pd.Timestamp(year=base_year, month=base_month, day=1)取的是每个月的第1天,而原始数据中的时间index是每个月的最后一天,因此while current_date in df.index这个指令是无效的,我们对原始数据的时间index加一条:
df.index = df.index + pd.offsets.MonthBegin(-1)
数据处理完成之后,再加一句:
df.index = df.index + pd.offsets.MonthEnd(0)
就可以得到我们想要的结果了
绝对值调整前
绝对值调整后
几点心得
- 借助AI编程,需要一点点的编程基础,至少知道AI给的程序是什么意思
- 需要很清晰的表述需求,不同的Prompt给的程序有时差别很多,需要尝试不同的Prompt
- 文中的几个例子,笔者都自己写过,但是AI给的程序都更简洁,对于一个非科班程序员来说,AI一般来说经验更丰富一些
- AI给的代码,会有bug,需要一定的debug能力
- 因为AI可以很智能、很聪明的对话,所以借助AI编程,充满了乐趣
0
推荐