【发布时间】:2021-10-31 12:20:25
【问题描述】:
大家好,我正在研究包含以下示例的数据集:
数据包含 start_time、end_time、id 和 url。对于一个 id 和 url 组,我有不同的输入和输出值问题是输入和输出值在不同的行中,我想填充缺少的 end_time/start_time 值。为此,我必须使用以下逻辑:
- 如果我在 start_time 中有值并且结束时间为空,那么我必须考虑 end_time >= start_time 用最接近的 end_time 填充 end_time 并删除使用/匹配的行
- 在填充了所有具有star_time 的行并删除了已使用/匹配的行后,仍然保留了一些start_time 为空的行,然后我必须用与end_time 相同的值填充start_time。
- 如果没有为给定的 start_time 找到匹配的 end_time 值,那么我必须用相同的 start_time 值填充 end_time 值。
考虑到以上几点,预期的结果应该类似于以下,我分两个阶段给出输出,以便于理解
目前我正在使用以下方式来实现这一点,但我觉得它没有优化:
def process(self, param, context):
df = context['data']
# df = df.drop_duplicates()
key_cols = param['keys_cols']
start_time_col = param['start_time_col']
end_time_col = param['end_time_col']
guid_col = param.get('guid_col','guid')
df_groupby = df.groupby(key_cols).size().reset_index()
final_dfs = []
condition = ''
for key in key_cols:
if condition == '':
condition = '(df[\''+str(key)+"\']==row[\'"+str(key)+"\'])"
else:
condition = condition + ' & ' +'(df[\'' + str(key) + "\']==row[\'" + str(key) + "\'])"
for index, row in df_groupby.iterrows():
sub_df = df[eval(condition)]
if sub_df[start_time_col].isnull().sum() != len(sub_df[start_time_col]) and (sub_df[end_time_col].isnull().sum() != len(sub_df[end_time_col])):
sub_df = sub_df.sort_values([start_time_col, end_time_col], ascending=True)
subdf_start_time_not_null = sub_df[sub_df[start_time_col].notnull()]
subdf_end_time_not_null = sub_df[sub_df[end_time_col].notnull()]
subdf_end_time_not_null['combined'] = subdf_end_time_not_null[end_time_col] +"__"+ subdf_end_time_not_null[guid_col]
end_time_values = subdf_end_time_not_null['combined'].values.tolist()
for row_number, (stime_index, stime_row) in enumerate(subdf_start_time_not_null.iterrows()):
delete_index = row_number
if row_number < len(end_time_values):
end_time_value = np.nan
if int(str(subdf_start_time_not_null.at[stime_index,start_time_col]).replace(":","").replace(" ","").replace("-","")) <= int(str(end_time_values[row_number]).split("__")[0].replace(":","").replace(" ","").replace("-","")):
end_time_value = end_time_values[row_number]
subdf_start_time_not_null.at[stime_index,end_time_col] = str(end_time_values[row_number]).split("__")[0]
else:
prev_index = end_time_values.index(end_time_values[row_number])
for end_time in end_time_values:
current_index = end_time_values.index(end_time)
if current_index > prev_index:
if int(str(subdf_start_time_not_null.at[stime_index,start_time_col]).replace(":","").replace(" ","").replace("-","")) <= int(str(end_time_values[current_index]).split("__")[0].replace(":","").replace(" ","").replace("-","")):
subdf_start_time_not_null.at[stime_index, end_time_col] = end_time_values[current_index]
delete_index = current_index
end_time_value = end_time_values.pop(delete_index)
break
subdf_end_time_not_null = subdf_end_time_not_null[subdf_end_time_not_null[guid_col]!=end_time_value.split("__")[1]]
else:
subdf_start_time_not_null.at[stime_index,end_time_col] = subdf_start_time_not_null.at[stime_index,start_time_col]
subdf_end_time_not_null.drop('combined', axis=1, inplace=True)
sub_df = pd.concat([subdf_start_time_not_null,subdf_end_time_not_null])
sub_df[start_time_col] = np.where(sub_df[start_time_col].isnull(),sub_df[end_time_col],sub_df[start_time_col])
sub_df[end_time_col] = np.where(sub_df[end_time_col].isnull(),sub_df[start_time_col],sub_df[end_time_col])
final_dfs.append(sub_df)
# LOGGER.info('do something' +str(index))
df = pd.concat(final_dfs)
context['data'] = df
context['continue'] = True
return context
其中参数如下:
param = {"keys_cols":['id', 'url'], "start_time_col":"start_time","end_time_col":"end_time"}
“df”是数据。
请帮助审查并提出如何使其更优化的建议,我在一个文件中有超过 70000 行数据和超过 12000 对 id 和 urls
期待你们。
谢谢
【问题讨论】:
-
您的问题几乎没有问题:我无法从描述中理解“使用”行。如果您简化您的询问,您将能够获得更多帮助。您是否考虑过将开始时间和结束时间放在一个列中,然后根据顺序重新创建新值?
-
@S2L used 指的是与最近结束时间匹配的行,如果造成混淆,请见谅。我改变了我的说法。关于将两个值放在一列中,但这将如何解决我的问题
标签: python pandas dataframe pandas-groupby rows