Spritesheet coordinates vs single sprite image index

Hi everyone.

So I'm passed the point of initial learning and I decided to start over again, now a bit more professional.
I had a project going that worked really well, but the code was extremely sloppy and became too
chaotic to handle anyway.

Now one of the more important things in my project is a character creation menu. In the old project I
imported each combination as a single sprite, but with multiple subimages. I then used image_index to animate the player, while getting the correct sprite using asset_get_index. The amount of needed assets was... well enough to slow down Game Maker significantly to the point of it becoming annoying.

A player exists out of, drawn in this order:

Each one of these has multiple spritesheets. I used to painfully just open a .png file, and import the subimages to a single sprite… for every possibilty. I thought: no way, this has to be possible to do more professional. So I started using the
draw_sprite_part functions. And it works pretty well! Now I only have to import a few spritesheets and just code my way through all the coordinates when they are needed.. No longer is Game Maker slowing down because of the enormous amounts of assets it needs to handle.
However, I can't seem to get it right. On very rare occasions, the coordinates seem to not update properly and 1-frame-only artifacts pop up somewhere on screen. The player does however, animate perfectly even with all the possible combinations layered on top of each other.

I've build my own "frame updater" to do this. For example, when a player walks left, the x and y coordinates on all these spritesheets update, and the draw event uses a more general updated variable for these coordinates.
When pressing left, a counter starts going: 0, 1, 2, 3, 4, 0, 1, 2, 3, 4, … To determine which frame of the animation needs to be drawn. Each frame has different coordinates on the spritesheet, and it works. But those damn artifacts sometime… I can't pinpoint the cause, and they flash by so quickly that I couldn't catch one in the act and provide a screenshot.
So something like

if (Player_Action = "Run")
Player_Frame += Player_FrameSpeed;
if (Player_Frame >= 0) && (Player_Frame < 1) {Player_X = 48} //the x coordinates on the spritesheet
if (Player_Frame >= 1) && (Player_Frame < 2) {Player_X = 32}
if (Player_Frame >= 2) && (Player_Frame < 3) {Player_X = 64}
if (Player_Frame >= 3) && (Player_Frame < 4) {Player_X = 32}
if (Player_Frame >= 4) {Player_Frame = 0}

if (Player_Direction = "Down") {Player_Y = 144;} //the y coordinates on the spritesheet
if (Player_Direction = "Up") {Player_Y = 176;}
if (Player_Direction = "Left") {Player_Y = 208;}
if (Player_Direction = "Right") {Player_Y = 240;}

//sprite width and sprite height are already predetermined somewhere else//

To give an idea: a single spritesheet is 1024x1024 pixels. I pretty much drew all of the possible player actions like walk, run, hold, run & hold, idle, attack, faint, stab, sleep, eat,... A spritesheet for the "shirt" has, in the exact same coordinates, shirts! When layered over the previous one, it all fits nicely. That way I only have to update the coordinates once, then layer them in the draw event:

draw_sprite_part(body spritesheet, coordinates: Player_X, Player_Y)
draw_sprite_part(shirt spritesheet, same coordinates)
...and so on.

Not a lot of code in the end, and it can handle an enormous amount of possibilities for the player graphics. But those artifacts… Even if it happens only once every 5 minutes or so without knowing the cause, if my eye catches it my mind goes "that needs to go because that doesn't look professional".

So… What do you suggest? Continue using draw_sprite_part and forget about importing every possibility (which did work perfectly); or go back to importing all those player actions on the spritesheets and have a ton of assets just for the player?