You are on the right track in controlling the number of positions. Maybe something like this for your 'before_trading_start' method.
# It's typical to sort the returned dataframe by some column or columns to order the stocks "best to worst"
# Simply use the 'sort_values' method
# Something like this (arbitrarily chose 'eps_rank')
context.longs_df = context.output.sort_values('eps_rank', ascending = False)
# Next it's also typical to hold only the 'best' stocks and sell everything else
# This strategy makes it easy to determine how many to buy
# In a more complex strategy, perhaps where you want a minimum hold time, then
# the calculation for qty_to_buy would be more involved (eg target - qty_holding_min_time)
# Simply use the 'head' method
qty_to_buy = context.target_qty_of_stocks
context.longs_df = context.longs_df.head(qty_to_buy)
# Creating a list of equity objects (rather than keeping the dataframe)
# isn't required but some do it as preference
context.longs = context.longs_df.index.tolist()
context.long_weight = weight(context)
Make sure you initialize 'context.target_qty_of _stocks' in the 'initialize' method.
Note that this will try to hold the target qty of stocks but if fewer than that pass your pipeline rules, then you may hold less. Occasionally you may also hold more if, for some reason, you aren't able to sell a position.
You asked about 'partial orders' in your portfolio. I believe you meant partial or fractional 'positions'. You really don't have them. You are probably seeing the values in the 'record' graph. Those display averages as the scale gets large. For example, if you have 20 positions one day and 19 the next, it may display 19.5. Zoom in on the graph and that phenomena will go away.