<SYSTEM_TASK:>
Solve the following problem using Python, implementing the functions described below, one line at a time
<END_TASK>
<USER_TASK:>
Description:
 def _find_first_transactions( transactions, customer_id_col, datetime_col, monetary_value_col=None, datetime_format=None, observation_period_end=None, freq="D", ):
 """ Return dataframe with first transactions. This takes a DataFrame of transaction data of the form: customer_id, datetime [, monetary_value] and appends a column named 'repeated' to the transaction log which indicates which rows are repeated transactions for that customer_id. Parameters transactions: :obj: DataFrame a Pandas DataFrame that contains the customer_id col and the datetime col. customer_id_col: string the column in transactions DataFrame that denotes the customer_id datetime_col: string the column in transactions that denotes the datetime the purchase was made. monetary_value_col: string, optional the column in transactions that denotes the monetary value of the transaction. Optional, only needed for customer lifetime value estimation models. observation_period_end: :obj: datetime a string or datetime to denote the final date of the study. Events after this date are truncated. If not given, defaults to the max 'datetime_col'. datetime_format: string, optional a string that represents the timestamp format. Useful if Pandas can't understand the provided format. freq: string, optional http://pandas.pydata.org/pandas-docs/stable/timeseries.html#dateoffset-objects """

    if observation_period_end is None:
        observation_period_end = transactions[datetime_col].max()

    if type(observation_period_end) == pd.Period:
        observation_period_end = observation_period_end.to_timestamp()

    select_columns = [customer_id_col, datetime_col]

    if monetary_value_col:
        select_columns.append(monetary_value_col)

    transactions = transactions[select_columns].sort_values(select_columns).copy()

    # make sure the date column uses datetime objects, and use Pandas' DateTimeIndex.to_period()
    # to convert the column to a PeriodIndex which is useful for time-wise grouping and truncating
    transactions[datetime_col] = pd.to_datetime(transactions[datetime_col], format=datetime_format)
    transactions = transactions.set_index(datetime_col).to_period(freq).to_timestamp()

    transactions = transactions.loc[(transactions.index <= observation_period_end)].reset_index()

    period_groupby = transactions.groupby([datetime_col, customer_id_col], sort=False, as_index=False)

    if monetary_value_col:
        # when we have a monetary column, make sure to sum together any values in the same period
        period_transactions = period_groupby.sum()
    else:
        # by calling head() on the groupby object, the datetime_col and customer_id_col columns
        # will be reduced
        period_transactions = period_groupby.head(1)

    # initialize a new column where we will indicate which are the first transactions
    period_transactions["first"] = False
    # find all of the initial transactions and store as an index
    first_transactions = period_transactions.groupby(customer_id_col, sort=True, as_index=False).head(1).index
    # mark the initial transactions as True
    period_transactions.loc[first_transactions, "first"] = True
    select_columns.append("first")
    # reset datetime_col to period
    period_transactions[datetime_col] = pd.Index(period_transactions[datetime_col]).to_period(freq)

    return period_transactions[select_columns]