The hosts looked on course for a defeat when substitute Luciano Vietto’s neat finish put Villarreal ahead after 79 minutes.
But Denis Suarez pounced on a loose ball to slam home the equaliser two minutes from time and, after Giovani dos Santos tripped Benoit Tremoulinas just inside the corner of the area, Bacca stepped up to slot home the penalty.
Champions Atletico Madrid are two points off the top in fifth after a hard-fought 1-0 win at Getafe.
Mario Mandzukic scored the only goal of the game in the 40th minute and the visitors’ task was made simpler by the dismissal of defender Alexis shortly before the hour mark.
Malaga cruised to a third consecutive league win with a dominant display in a 4-0 victory against Rayo Vallecano.
Nordin Amrabat was the star of the show for the hosts, causing havoc down Rayo’s left-hand side and through the middle, and was involved in all four goals.
Samuel Garcia, Sergi Darder, Juanmi and then finally Amrabat all got on the scoresheet.
Elsewhere, Espanyol and Deportivo La Coruna played out a dour 0-0 draw.