2
$\begingroup$

Short version:
Given I have a list of 120 traits (happy, sad, etc.) evaluated on a number of scales ranging from -5 (for example highly negative) to +5 (for example highly positive), how can I group these traits into 6 sets of 20 items each, so that each set has a similar mean and variance of those scales?

A word of explanation: The 120 traits will be judged on whether or not they describe one of 6 social objects (20 traits per object) (using a 1-5 scale). Traits I will be using come from a bigger set (of 300 unique items) where each has been evaluated on measures like: valence, agency, communion and a couple of others.

I'd like to make sure that each social object was judged on traits that overall had a similar mean and (possibly) standard deviation, so that I don't end up, with one object that had very extreme traits (highly negative and highly positive) while others where somewhere in the middle.

R data example:

This is a minimal data example.
Note that in my real data, measures (valence etc) are not necessarily normally distributed and most likely correlated with other measures.

I did some reading and found out my problem might be partitioning related. Here is a R code I made up that does (more or less) what I'd like, but only based on one variable (let's pretented x are ratings of valence).

library(tidyverse)

set.seed(1)
x<- rnorm(120) # normal distribution is just an example
x<- sort(x)
g1<- rep(1:6, 20) # grouping strategy 1
g2<- rep(c(1:6, 6:1), 10) # grouping strategy 2
df<- tibble(x, g1, g2)


df %>%
    group_by(g1) %>%
    summarise(mean = mean(x), var = var(x))

df %>%
    group_by(g2) %>%
    summarise(mean = mean(x), var = var(x))

With the above code I can see that strategy #2 yields better results, as means of groups are more similar than with strategy #1. q

# A tibble: 6 x 3
     g1       mean       var
  <int>      <dbl>     <dbl>
1     1 0.01216328 0.8462127
2     2 0.05113158 0.8146632
3     3 0.08567107 0.7907553
4     4 0.13632257 0.7679591
5     5 0.16613787 0.7915441
6     6 0.20683895 0.8273733

# A tibble: 6 x 3
     g2      mean       var
  <int>     <dbl>     <dbl>
1     1 0.1078368 0.9842131
2     2 0.1094842 0.8930841
3     3 0.1104103 0.8232504
4     4 0.1115834 0.7368137
5     5 0.1077852 0.7200830
6     6 0.1111654 0.7093138

What I can't figure out is how to work with a couple of ranking variables (above example had only x).

In other words, what would be the best strategy to find the best possible grouping solution for a dataframe like this:

data<- data.frame(
      trait_number = seq(1:120), 
      valence_rating = rnorm(120, mean = 0, sd = 3),
      agency_rating = rnorm(120, mean = 0, sd = 3),
      communion_rating = rnorm(120, mean = 0, sd = 3),
      grouping = NA)

(note: once again rnorm is just an example for sample data. My real data is not normally distributed)

If I can explain anything more, please let me know in comments. Thank you.

$\endgroup$
8
  • $\begingroup$ This thing is really bugging me and I would love to offer a bounty if only I could. $\endgroup$
    – blazej
    Commented Nov 24, 2017 at 20:33
  • 1
    $\begingroup$ I don't understand what you want to do. Given the data in your R code, you want to divide up the observations into groups? Like, group 1 would be observations with valence around -1, agency around 1, and communion around 0. Group 2 would be observations with valence around 2, agency around 0, and communion around 0. Etc? Like that or something else? $\endgroup$
    – Bill
    Commented Nov 25, 2017 at 18:08
  • 1
    $\begingroup$ Unfortunately, this is not something I know about. I googled and found that this is a topic which comes up in cross-validation. The paper I link below suggests an algorithm which is 1) choose an element randomly and assign it to set 1. 2) find the closest 5 elements to the one you chose in step 1 and assign these to sets 2 through 6. 3) keep doing this until you run out of elements or your sets are full. You need to operationalize closest in step 2 with some distance measure. $\endgroup$
    – Bill
    Commented Nov 25, 2017 at 19:05
  • 1
    $\begingroup$ researchgate.net/profile/Jose_Moreno-Torres/publication/… $\endgroup$
    – Bill
    Commented Nov 25, 2017 at 19:05
  • 1
    $\begingroup$ for a dataframe like this:, and then follows some code, not the data. It is a very bad practice to not show data, only to show uncommented code, R in this instance, - because some people may be not R users. $\endgroup$
    – ttnphns
    Commented Dec 9, 2017 at 9:05

1 Answer 1

1
$\begingroup$

I have a mutlivariate nonparametric regression method that uses clusters. Using the cluster ID's to sort the data, then assigning a group to that sorted data yields the following results with your data df:

require(NNS)

a=NNS.reg(cbind(data$valence_rating,data$agency_rating,data$communion_rating),
      rep(1,length(data$trait_number)))$Fitted.xy

setkey(a,NNS.ID)

colnames(a)[1:3]=colnames(data[,2:4])


# Re-run from here with different group innovations
a[,`:=` (group=rep(1:6, 20))]

a[,{valence_mean=mean(valence_rating);valence_sd=sd(valence_rating)
    agency_mean=mean(agency_rating);agency_sd=sd(agency_rating)
    communion_mean=mean(communion_rating);communion_sd=sd(communion_rating)
    list(valence_mean=valence_mean,valence_sd=valence_sd,
         agency_mean=agency_mean,agency_sd=agency_sd,
         communion_mean=communion_mean,communion_sd=communion_sd)
    }, by=group]



   group valence_mean valence_sd agency_mean agency_sd communion_mean communion_sd
1:     1  -0.06839077   2.674746 -0.61403779  3.024703     -0.1573398     2.455025
2:     2  -0.73164854   3.603836 -0.06347979  2.197635      0.5897524     3.638972
3:     3   0.87995369   2.425216 -0.70785458  2.915249     -0.1070705     3.266067
4:     4   0.34903443   2.667286 -0.67996477  3.295273      0.4793330     2.250582
5:     5   0.32653867   3.204289  0.35996665  3.191802      0.5791942     3.786095
6:     6   0.82249408   3.037100 -0.18225506  3.531984     -0.3244441     3.280554

I'm sure it could be better, but hopefully this gets you started and it's applicable to your actual data.

$\endgroup$

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

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