Python 复制数据帧行并同时更新数据帧值的有效方法
我需要一些帮助来优化我的python代码。代码根据数据帧中的一行中的值多次复制该行 我将尝试描述它的功能:Python 复制数据帧行并同时更新数据帧值的有效方法,python,pandas,dataframe,date,optimization,Python,Pandas,Dataframe,Date,Optimization,我需要一些帮助来优化我的python代码。代码根据数据帧中的一行中的值多次复制该行 我将尝试描述它的功能: 数据框有三个日期列:拆分日期、开始日期和结束日期,以及一个状态列,其中包含“in”或“out”。dataframe将有更多列,但其余列在算法中并不重要 它使用溢出日期的mm/dd来创建 开始日期和结束日期之间的日期。假设拆分日期为2000-02-15,开始日期为2010-03-26,并且 截止日期为2012年12月31日。日期列表将为2010年03月26日、2011年02月15日, 2
- 数据框有三个日期列:拆分日期、开始日期和结束日期,以及一个状态列,其中包含“in”或“out”。dataframe将有更多列,但其余列在算法中并不重要
- 它使用溢出日期的mm/dd来创建 开始日期和结束日期之间的日期。假设拆分日期为2000-02-15,开始日期为2010-03-26,并且 截止日期为2012年12月31日。日期列表将为2010年03月26日、2011年02月15日, 2012-02-15和2012-12-31
- 根据日期列表,它将复制原始dataframe行和 用日期列表中的日期替换开始日期和结束日期。 使用相同的示例,原始行将被复制 三次,开始日期和结束日期为:
- 2010-03-26和2011-02-15
- 2011-02-15和2012-02-15
- 2012-02-15和2012-12-31
- 除最后一行的状态与原始行相同外,所有新创建的行的状态均为“in”。以同样的例子:
- 如果原始行中的状态为“in”,则三个重复行的状态为“in”
- 如果原始行中的状态为“out”,则新创建行的第一行和第二行的状态为“in”,第三行的状态为“out”
import pandas as pd
import numpy as np
data = {"name": ["a","b","c","d"],
"status": ["out","out","in","out"],
"split_date": ["2000-02-15","2010-12-31","1984-02-29","2000-03-31"],
"start_date": ["2010-03-26","2010-01-01","2015-06-15","2012-11-18"],
"end_date": ["2012-12-31","2015-12-31","2020-03-01","2018-07-19"]}
df = pd.DataFrame(data)
df["split_date"]=pd.DatetimeIndex(df["split_date"]).normalize()
df["start_date"]=pd.DatetimeIndex(df["start_date"]).normalize()
df["end_date"]=pd.DatetimeIndex(df["end_date"]).normalize()
def to_split(df,start_column,end_column,split_column):
"""
df = name of the dataframe whose dates are to be split
start_column = column name of start date
end_column = column name of end date
split_column = column name of split date (only mm-dd of the date will be used)
"""
dict_df = df.to_dict(orient="index")
dictionary_list=[]
for key,row_dict in dict_df.items():
first_date=row_dict[start_column]
last_date=row_dict[end_column]
if last_date < first_date:
raise ValueError("end_column_date is before start_column_date.")
try:
splitter = pd.Timestamp(first_date.year,row_dict[split_column].month,row_dict[split_column].day)
except: #leap day
splitter = pd.Timestamp(first_date.year,row_dict[split_column].month,row_dict[split_column].day-1)
#Create a date list to store intermediate split date between first_date and last_date
date_list=[]
date_list.append(first_date)
last_boolean=False
while last_boolean == False:
if splitter <= first_date and splitter <= last_date:
try:
splitter = pd.Timestamp(splitter.year+1,row_dict[split_column].month,
row_dict[split_column].day)
except: #leap day
splitter = pd.Timestamp(splitter.year+1,row_dict[split_column].month,
row_dict[split_column].day-1)
elif splitter > first_date and splitter <= last_date:
date_list.append(splitter)
try:
splitter = pd.Timestamp(splitter.year+1,row_dict[split_column].month,
row_dict[split_column].day)
except: #leap day
splitter = pd.Timestamp(splitter.year+1,row_dict[split_column].month,
row_dict[split_column].day-1)
else: #splitter > last_date
date_list.append(last_date)
last_boolean = True
#convert list to dictionary first to remove any duplicate then convert back to list again
date_list = list(dict.fromkeys(date_list))
date_list.sort()
no_segment = len(date_list)-1
status=row_dict["status"]
for i in range(no_segment):
#Assign new start and end date to each newly created row
row_dict["start_column_date"]=date_list[i]
row_dict["end_column_date"]=date_list[i+1]
#Assign new status to each newly created row
if i != no_segment-1:
row_dict["status"] = "in"
else:
row_dict["status"] = status
#dictionary_list.append(row_dict)
#results will be wrong because list contains a reference to the original dictionary
dictionary_list.append(row_dict.copy())
new_df=pd.DataFrame.from_dict(dictionary_list)
return new_df
expanded_df=to_split(df,"start_date","end_date","split_date")
expanded_df
将熊猫作为pd导入
将numpy作为np导入
数据={“名称”:[“a”、“b”、“c”、“d”],
“状态”:[“输出”、“输出”、“输入”、“输出”],
“拆分日期”:[“2000-02-15”、“2010-12-31”、“1984-02-29”、“2000-03-31”],
“开工日期”:[“2010-03-26”、“2010-01-01”、“2015-06-15”、“2012-11-18”],
“结束日期”:[“2012-12-31”、“2015-12-31”、“2020-03-01”、“2018-07-19”]
df=pd.DataFrame(数据)
df[“分割日期”]=pd.DatetimeIndex(df[“分割日期”]).normalize()
df[“开始日期”]=pd.DatetimeIndex(df[“开始日期”]).normalize()
df[“结束日期”]=pd.DatetimeIndex(df[“结束日期”]).normalize()
def到_拆分(df、开始_列、结束_列、拆分_列):
"""
df=要拆分其日期的数据帧的名称
开始\列=开始日期的列名
结束\列=结束日期的列名
split_column=拆分日期的列名(仅使用日期的mm dd)
"""
dict_df=df.to_dict(orient=“index”)
字典列表=[]
对于键,dict_df.items()中的行dict:
第一个日期=行记录[开始列]
最后日期=行记录[结束列]
如果最后日期<第一日期:
raise VALUE ERROR(“结束列日期早于开始列日期”)
尝试:
splitter=pd.Timestamp(第一个日期.年,行记录[拆分列]。月,行记录[拆分列]。天)
除了:#闰日
splitter=pd.Timestamp(第一个日期.年,行记录[拆分列]。月,行记录[拆分列]。第1天)
#创建日期列表以存储第一个日期和最后一个日期之间的中间拆分日期
日期列表=[]
日期列表。附加(第一个日期)
最后一个布尔值=False
而last_boolean==False:
如果根据我的经验,斯普利特提出了大量文本和大量代码的问题,却得不到任何答案,那么就没有人愿意通读所有文本和代码来理解问题所在。尽量简短扼要。我自己的一个问题,看到区别了吗?太多了,无法理解-但是在数据帧上迭代总是一个坏主意。将范例从循环切换到基于最佳向量,或者使用掩码和子掩码。我知道在数据帧上迭代是个坏主意。我曾尝试使用矢量化操作,但我不认为它可以在这种情况下使用,因为我实际上是根据每一行的输入创建新行。我可能会错过一些东西,所以一些关于矢量化操作的指针会很好。根据我的经验,有大量文本和大块代码的问题不会得到任何答案,没有人想通过所有文本和代码来理解问题是什么。尽量简短扼要。我自己的一个问题,看到区别了吗?太多了,无法理解-但是在数据帧上迭代总是一个坏主意。将范例从循环切换到基于最佳向量,或者使用掩码和子掩码。我知道在数据帧上迭代是个坏主意。我曾尝试使用矢量化操作,但我不认为它可以在这种情况下使用,因为我实际上是根据每一行的输入创建新行。我可能会错过一些东西,所以向量化操作上的一些指针会很好。