0
$\begingroup$

I have the following data frame:

>df
   Name
 1 Ed
 2 Ed
 3 Bill
 4 Tom
 5 Tom
 6 Tom
 7 Ed
 8 Bill
 9 Bill
10 Bill

My goal is that from each group by "Name" change the "Name" values 25-75% of random rows to "Name"+"_X" (the remaining rows don't change). So the expected output is similar to:

   Name
 1 Ed
 2 Ed_X
 3 Bill_X
 4 Tom
 5 Tom_X
 6 Tom
 7 Ed_X
 8 Bill
 9 Bill
10 Bill_X

I have tried with for cycle like this (a the moment, for 50% random rows:

for (n in unique(df$Name)){
  df[sample(which(df$Name==n), nrow(df[df$Name==id,])/2), 1] <- paste(df$Name, "_X", sep="")
}

Unsuccessfully, however.

$\endgroup$
1
$\begingroup$

The idea is correct, even if you have a couple of mistakes in your code (like id is not defined, and inside paste you want to use just n, not df$Name). This is not super compressed code but it does the job:

Name = c('Ed','Ed','Bill','Tom','Tom','Tom','Ed','Bill','Bill','Bill')
df = data.frame(Name)

for (n in unique(df$Name)){

    # get indices 
    indices = which(df$Name==n)

    # sample size
    samp_size = round(length(df[df$Name==n,])/2)

    # get indices to replace
    samp = sample(indices, samp_size)

    # need to set column as character
    df$Name = as.character(df$Name)

    # set new values
    df[samp,] =  paste(n,'_X',sep='')

    # set again column as factor 
    df$Name = as.factor(df$Name)
}

Out:

     Name
1      Ed
2    Ed_X
3    Bill
4   Tom_X
5   Tom_X
6     Tom
7    Ed_X
8    Bill
9  Bill_X
10 Bill_X
$\endgroup$
1
  • $\begingroup$ If you want to select sample_size also randomly, you can use round(runif(1, min=25, max=75)) which will return an integer between 25 and 75, and then use this value to calculate samp_size $\endgroup$ Mar 30 '20 at 18:46

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.