Python 在数据框中展开带有日期的值
我有一个带有名称值和日期范围(开始/结束)的数据框。我需要用from/to索引生成的日期展开/替换这些日期。我该怎么做Python 在数据框中展开带有日期的值,python,pandas,Python,Pandas,我有一个带有名称值和日期范围(开始/结束)的数据框。我需要用from/to索引生成的日期展开/替换这些日期。我该怎么做 Name date_range NameOne_%Y%m-%d [-2,1] NameTwo_%y%m%d [-3,1] 预期结果(假设今天的日期为2021-03-09-2021年3月9日): 我一直在尝试迭代数据帧,然后生成日期,但仍然无法使其工作 for index, row in s
Name date_range
NameOne_%Y%m-%d [-2,1]
NameTwo_%y%m%d [-3,1]
预期结果(假设今天的日期为2021-03-09-2021年3月9日):
我一直在尝试迭代数据帧,然后生成日期,但仍然无法使其工作
for index, row in self.config_df.iterrows():
print(row['source'], row['date_range'])
days_sub=int(str(self.config_df["date_range"][0]).strip("[").strip("]").split(",")[0].strip())
days_add=int(str(self.config_df["date_range"][0]).strip("[").strip("]").split(",")[1].strip())
start_date = date.today() + timedelta(days=days_sub)
end_date = date.today() + timedelta(days=days_add)
date_range_df=pd.date_range(start=start_date, end=end_date)
date_range_df["source"]=row['source']
感谢您的帮助。谢谢 好的。从您的问题中,我了解到您有这样一个起始数据框:
config\u df=pd.DataFrame({
'name':['NameOne_%Y-%m-%d','NameOne_%Y%m%d'],
'str_date_range':['[-2,1]','[-3,1]']})
因此:
name str_date_range
0 NameOne_%Y-%m-%d [-2,1]
1 NameTwo_%y%m%d [-3,1]
为了实现您的目标并避免重复行(使用pandas应该避免重复行),您可以使用groupby().apply()
如下所示:
def展开(行):
#通过拆分从行中获取开始日期和结束日期
#字符串和分别取第一个和最后一个值。
#.min()是必需的,因为从技术上讲,行是pd.Series
start_date=row.str_date_range.str.strip('[]').str.split(',').str[0].astype(int).min()
end_date=row.str_date_range.str.strip('[]').str.split(',').str[1].astype(int).min()
#创建从开始日期到结束日期的列表范围。
#请注意,range()不包括结束日期,因此添加1
日期范围=范围(开始日期、结束日期+1)
#从day_范围创建时间增量系列
日差=日到时差(日系列(日范围),单位为日)
#创建一系列大小相同的时间戳
todays=pd.Series(pd.Timestamp.today())。repeat(len(day\u范围)-1)。reset\u index(drop=True)
df=今天。到_帧(name='date')
#将日期差异添加到日期列
df['date']=df.date+天数
df['name']=row.name
#从名称中提取日期格式
日期\格式=行.名称.拆分(“”“”)[1]
#使用日期\格式字符串添加带有格式化日期的列
df['date\u str']=df.date.dt.strftime(日期格式=日期格式)
df['name']=df.name.str.split(''u').str[0]+''u'+df.date\u str
#可选:下拉列
返回df.drop(列=['date'])
config_df.groupby('name')。apply(展开)。reset_索引(drop=True)
返回:
name date_str
0 NameOne_2021-03-07 2021-03-07
1 NameOne_2021-03-08 2021-03-08
2 NameOne_2021-03-09 2021-03-09
3 NameTwo_210306 210306
4 NameTwo_210307 210307
5 NameTwo_210308 210308
6 NameTwo_210309 210309
好的。从您的问题中,我了解到您有这样一个起始数据框:
config\u df=pd.DataFrame({
'name':['NameOne_%Y-%m-%d','NameOne_%Y%m%d'],
'str_date_range':['[-2,1]','[-3,1]']})
因此:
name str_date_range
0 NameOne_%Y-%m-%d [-2,1]
1 NameTwo_%y%m%d [-3,1]
为了实现您的目标并避免重复行(使用pandas应该避免重复行),您可以使用groupby().apply()
如下所示:
def展开(行):
#通过拆分从行中获取开始日期和结束日期
#字符串和分别取第一个和最后一个值。
#.min()是必需的,因为从技术上讲,行是pd.Series
start_date=row.str_date_range.str.strip('[]').str.split(',').str[0].astype(int).min()
end_date=row.str_date_range.str.strip('[]').str.split(',').str[1].astype(int).min()
#创建从开始日期到结束日期的列表范围。
#请注意,range()不包括结束日期,因此添加1
日期范围=范围(开始日期、结束日期+1)
#从day_范围创建时间增量系列
日差=日到时差(日系列(日范围),单位为日)
#创建一系列大小相同的时间戳
todays=pd.Series(pd.Timestamp.today())。repeat(len(day\u范围)-1)。reset\u index(drop=True)
df=今天。到_帧(name='date')
#将日期差异添加到日期列
df['date']=df.date+天数
df['name']=row.name
#从名称中提取日期格式
日期\格式=行.名称.拆分(“”“”)[1]
#使用日期\格式字符串添加带有格式化日期的列
df['date\u str']=df.date.dt.strftime(日期格式=日期格式)
df['name']=df.name.str.split(''u').str[0]+''u'+df.date\u str
#可选:下拉列
返回df.drop(列=['date'])
config_df.groupby('name')。apply(展开)。reset_索引(drop=True)
返回:
name date_str
0 NameOne_2021-03-07 2021-03-07
1 NameOne_2021-03-08 2021-03-08
2 NameOne_2021-03-09 2021-03-09
3 NameTwo_210306 210306
4 NameTwo_210307 210307
5 NameTwo_210308 210308
6 NameTwo_210309 210309
使用
ast
模块将您的date\u范围从str
转换为list
:
import ast
df = df.assign(date_range=df["date_range"].apply(ast.literal_eval)
使用date\u range
创建日期列表,并使用explode
链接列表:
today = pd.Timestamp.today().normalize()
offset = pd.tseries.offsets.Day # shortcut
names = pd.Series([pd.date_range(today + offset(end),
today + offset(start),
freq="-1D").strftime(name)
for name, (start, end) in df.values]).explode(ignore_index=True)
使用ast
模块将您的date\u范围从str
转换为list
:
import ast
df = df.assign(date_range=df["date_range"].apply(ast.literal_eval)
使用date\u range
创建日期列表,并使用explode
链接列表:
today = pd.Timestamp.today().normalize()
offset = pd.tseries.offsets.Day # shortcut
names = pd.Series([pd.date_range(today + offset(end),
today + offset(start),
freq="-1D").strftime(name)
for name, (start, end) in df.values]).explode(ignore_index=True)
您的目标是从config_df
生成一个简单的序列吗?我的目标是拥有一个全新的数据帧,每一行每天重复一次。我不仅需要日期序列,我还需要“名称”以及每个名称所需格式的日期。(例如,对于用2021年替换%Y的每个名称)您的目标是从config_df
生成一个简单的系列吗?我的目标是拥有一个全新的数据帧,每一行每天重复一次。我不仅需要日期序列,我还需要“名称”以及每个名称所需格式的日期。(例如,对于用2021年替换%Y的每个名称)好的解决方案!一个问题:我们能用df简化行吗?将分配给df[“date\u range”]=df[“date\u range”]。应用(ast.literal\u eval)
df.assign
创建一个新的数据框。除了所有现有列之外,还包含新列。因此,如果我们只是更新一列,为什么需要创建整个数据帧的副本?df.assign
不会创建新列如果名称date\u范围
与现有列相同,它会覆盖它。如果您愿意,可以使用df[“日期范围”]
,它不会改变任何东西。我更喜欢使用assign
,因为我可以链接多个函数<代码>df[“日期范围”]=df[“日期范围”]。应用(ast.literal\u eval)
是,了解使用相同列时没有创建新列n