Olá Janderson tudo bom? =)
Gostando de ver seu empenho!
Vamos as questões!
"Primeiro, se os valores são gerados aleatoriamente, o que garante que eles vão começar do número 1 e ir até 400, não poderia aparecer números, por exemplo, [741, 546, 899]? Qual linha de código garante isso?"
Certo. Nós garantimos isso nessa parte aqui:
total_alunos = len(nomes)
Pois determinamos que a variável total_alunos terá como tamanho máximo o comprimento da nossa lista de nomes ou seja, 400. O len garante isso.
nomes_f = pd.read_json("https://servicodados.ibge.gov.br/api/v1/censos/nomes/ranking?qtd=200&sexo=f")
nomes_m = pd.read_json("https://servicodados.ibge.gov.br/api/v1/censos/nomes/ranking?qtd=200&sexo=m")
print("Quantidade de nomes: " + str(len(nomes_f) + len (nomes_m)))
Quantidade de nomes: 400
Nessa parte tínhamos a informação do tamanho da lista nomes. Assim não surgirão números fora desse raio.
"Segundo, se os valores gerados já são aleatórios, ou seja, não vão aparecer em sequência no DataFrame, porque utilizar o permutation?"
Conforme a documentação técnica que vemos AQUI
Parâmetros
x int ou array_like
Se x é um número inteiro, permute aleatoriamente np.arange(x). Se x for uma matriz, faça uma cópia e embaralhe os elementos aleatoriamente.
Devoluções
fora ndarray
Sequência permutada ou intervalo de array.
Como podemos observar ali, no nosso exemplo ele faz uma cópia e embaralha os elementos aleatoriamente, pois se trata de uma matriz nosso dataframe.
"nomes['ID alunos'] = np.random.permutation(total_alunos) + 1
Por fim, qual a finalidade de somar um?"
Nessa parte o +1 é colocado para que não exista índice(ID) 0(zero) para os nossos alunos. Então no lugar da lista correr de 0 à 399 ela corre de 1 à 400.
Espero que eu tenha esclarecido suas dúvidas! Até a próxima Janderson!
Bons estudos!