0

I have been struggling to figure out how to weight the length of an array. I would like to weight specific columns in an array, so that the array has a different number of columns based on said weights.

The current output of my script is

`# Output 1
['green eyes', 'black hair', 'girl', 'human', 'happy', 'propeller beanie', 'kitsune mask', 'smurk', 'horns', 'monocle', 'wings', 'halo', [...]]
# Output 2
['brown eyes', 'brown hair', 'boy', 'human', 'tired', 'propeller beanie', 'oni mask', 'frowning', 'cat ears', 'tail', 'bat wings', 'halo', [...]]`

I am aiming for an output such as

`# Output1
['green eyes, 'black hair', 'girl', 'happy', 'smurk']
# Output2
['green eyes, 'black hair', 'girl', 'elf', 'sad', 'horns', 'wings']
# Output3
['green eyes, 'black hair', 'girl', 'kitsune mask']`

The items in the output are apart of separate weighted lists. for example

`feeling = ["tired", "happy", "sad", "grumpy",]`

I would like column 3 to have an 18% chance of using an item from feeling, and feeling has a 32% chance of being "happy". Currently, column 3 has a 100% chance of being from feeling, and feeling has a 32% chance of being "happy". I welcome other methods than using an array to achieve the same result.

I tried shortening the array to column 2, and created a list of columns 3 through 11. Then, using random.choices, I weighted the list and added the output of the array with the weighted list. However, this only gives me a single value from the weighted list, which allows for duplicate items to array when iterating. I iterated the weighted list in an attempt to have multiple outputs with varying number of columns.

The block of code I'm working with is the following

modelSexOdds = random.choices(modelSex, weights=(50, 50))  # always
raceOdds = random.choices(race, weights=(6, 10, 3, 9, 60, 5, 7))
feelingOdds = random.choices(feeling, weights=(15, 32, 29, 24))
hairOdds = random.choices(
    hairColor, weights=(13, 8, 12, 11, 5, 7, 10, 8, 6, 5, 8, 4, 2, 1)
)
eyeOdds = random.choices(
    eyeColor, weights=(13, 8, 12, 11, 5, 7, 10, 8, 6, 5, 8, 4, 2, 1)
)
headWearOdds = random.choices(headWear, weights=(27, 14, 13, 15, 10, 7, 5, 2, 7))
faceWearOdds = random.choices(faceWear, weights=(5, 20, 23, 35, 17))
expressionOdds = random.choices(expression, weights=(15, 47, 38))
miscOdds = random.choices(misc, weights=(30, 40, 10))
classyOdds = random.choices(classy, weights=(25, 8, 36, 31))
wingsOdds = random.choices(wings, weights=(37, 26, 37))

traits = [
    "Eye Color",
    "Hair Color",
    "Sex",
    "Race",
    "Feeling",
    "Head Wear",
    "Face Wear",
    "Expression",
    "Misc",
    "Classy",
    "Wings",
    "Divine",
]

trait_options = {
    trait_name: [
        os.path.splitext(x)[0]
        for x in os.listdir("scripts/Prompts/assets/" + trait_name)
    ]
    for trait_name in traits
    if trait_name != "modelSex"
}
trait_options["Eye Color"] = eyeOdds
trait_options["Hair Color"] = hairOdds
trait_options["Sex"] = modelSexOdds
trait_options["Race"] = raceOdds
trait_options["Feeling"] = feelingOdds
trait_options["Head Wear"] = headWearOdds
trait_options["Face Wear"] = faceWearOdds
trait_options["Expression"] = expressionOdds
trait_options["Misc"] = miscOdds
trait_options["Classy"] = classyOdds
trait_options["Wings"] = wingsOdds
trait_options["Divine"] = divine


max_possible_combinations = math.prod([len(trait_options[t]) for t in trait_options])

# eyeColor, 0 | 100%
# hairColor, 1 | 100%
# modelSex, 2 | 100%
# raceOdds, 3 | 22%
# feelingOdds, 4 | 18%
# headWearOdds, 5 | 12%
# faceWearOdds, 6 | 9%
# expressionOdds, 7 | 15%
# miscOdds, 8 | 10%
# classyOdds, 9 | 7%
# wingsOdds, 10 | 6%
# divineOdds, 11 | 1%
traitsOdds = [
    raceOdds,
    feelingOdds,
    headWearOdds,
    faceWearOdds,
    expressionOdds,
    miscOdds,
    classyOdds,
    wingsOdds,
    divine,
]

allOdds = random.choices(traitsOdds, weights=(22, 18, 12, 9, 15, 10, 7, 6, 1))
print(allOdds)
dnas = []

for i in range(2):
    dna = {}
    for t in traits:
        dna[t] = trait_options[t][random.randint(0, len(trait_options[t]) - 1)]
    dnas.append(dna)

for dna in dnas:
    text_config = []
    for trait_name, trait_value in dna.items():
        if trait_name == "modeSexx":
            pass
        else:
            text_config.append(f"{trait_value}")
    text_config.append(text_config)
print(text_config)`
```
Norepi
  • 1
  • 1
  • 2
    This is duplicate of this question https://stackoverflow.com/questions/3679694/a-weighted-version-of-random-choice – Richard Plester Nov 07 '22 at 21:09
  • Thank you for providing that link. I played around with some of the code found in the answers. Is seems like using a numpy array was the only way that I was able to have a weighted length. Can the length of a list or array be weighted using random.choices if weights are already defined? – Norepi Nov 10 '22 at 22:44
  • Does this answer your question? [A weighted version of random.choice](https://stackoverflow.com/questions/3679694/a-weighted-version-of-random-choice) – Pravash Panigrahi May 07 '23 at 10:29

0 Answers0