У меня есть Pandas df, как определено ниже:
ID Start End
0 77 2018-07-02 2020-07-02
1 88 2019-07-02 2021-07-02
2 99 2020-07-02 2022-07-02
Я хочу создать функцию для возврата следующего результата (строки):
((Date BETWEEN '2018-07-02' AND '2020-07-02') AND ID = 77)
OR ((Date BETWEEN '2019-07-02' AND '2021-07-02') AND ID = 88)
OR ((Date BETWEEN '2020-07-02' AND '2022-07-02') AND ID = 99)
Вот что я написал, но это не дало ожидаемого результата:
def create_string(df):
date_start = df.loc[
(df['ID'] == ID), 'Start']
date_end = df.loc[
(df['ID'] == ID), 'End']
date_string = F"(((Date BETWEEN '{date_start}' AND '{date_end}') AND ID = '{ID}') OR"
string = ""
final_string = string + date_string
return final_string
IDs = df.ID.copy()
for ID in IDs:
print(create_string(df))
Любые предложения будут ценны!






ты можешь сделать вот так
df["cond"] = df.apply(lambda r: f"((Date BETWEEN '{r['start']}' AND 'r['end']') AND ID = r['ID'])", axis=1)
тогда исходящая строка может быть рассчитана с помощью
final_str = " OR ".join(df["cond"].tolist())
Получил рабочий пример:
import pandas as pd
d = {'ID': [77,78,99], 'Start': ['2018-07-02', '2018-07-03', '2018-07-04'],
'End': ['2018-07-05', '2018-07-06', '2018-07-07']}
df = pd.DataFrame(data=d)
def create_string(df, id_, string):
date_start = df.loc[df['ID'] == id_].iloc[0,1]
date_end = df.loc[df['ID'] == id_].iloc[0,2]
date_string = F"(((Date BETWEEN '{date_start}' AND '{date_end}') AND ID = '{id_}') OR"
string += date_string
return string
string = ""
for id_ in [77, 78,99]:
string = create_string(df,id_, string)
print(string)
Ваши проблемы были:
Спасибо @matleg. Смотрите ошибку моего кода. Да, ты прав. Строка каждый раз переопределяется в функции.
Вы почти там. Вам просто нужно вызвать values[0] при доступе к датам и внести небольшие изменения в параметры функции.
def create_string(df, ID):
date_start = df.loc[
(df['ID'] == ID), 'Start'].values[0]
date_end = df.loc[
(df['ID'] == ID), 'End'].values[0]
date_string = f"((Date BETWEEN '{date_start}' AND '{date_end}') AND ID = {ID})"
return date_string
IDs = df.ID.copy()
strings = []
for ID in IDs:
strings.append(create_string(df, ID))
print(" OR\n".join(strings))
В качестве альтернативы вы можете написать это таким образом. Это делает ваш код намного чище.
def get_dates(df, ID):
date_start = df.loc[df['ID'] == ID, 'Start'].values[0]
date_end = df.loc[df['ID'] == ID, 'End'].values[0]
return date_start, date_end
def create_date_string(df, ID):
date_start, date_end = get_dates(df, ID)
date_string = f"((Date BETWEEN '{date_start}' AND '{date_end}') AND ID = {ID})"
return date_string
def create_all_strings(df):
IDs = df.ID.copy()
all_strings = [create_date_string(df, ID) for ID in IDs]
return " OR\n".join(all_strings)
print(create_all_strings(df))
Спасибо @Нил. Ваше второе решение лаконично!
Предполагая, что некоторые скобки избыточны, следующее будет работать с любым фреймом данных с вышеуказанной формой.
' OR '.join(map(lambda r: "(DATE BETWEEN '{}' AND '{}' AND ID = {})".format(r[1], r[2], r[0]), df.values.tolist()))
Выход:
"(DATE BETWEEN '2018-07-02' AND '2020-07-02' AND ID = 77) OR (DATE BETWEEN '2019-07-02' AND '2021-07-02' AND ID = 88) OR (DATE BETWEEN '2020-07-02' AND '2022-07-02' AND ID = 99)"
Спасибо @Xiaomin. Добавьте фигурные скобки к r['end'] и r['ID'], тогда ваш код будет работать хорошо.