Path of solutions list within Complex, Intermediate and Parsimonious objects

40 views
Skip to first unread message

Luigi Rombi

unread,
Jan 24, 2024, 2:06:11 PM1/24/24
to QCA with R
Dear Adrian, dear All, 
I have encountered some issues finding a path within the object that have been created from my truth table. 

In essence, I was convinced that the solutions' list was always contained in object$essential for Complex and Parsimonious objects (e.g., Complex_2016$essential) and in names(object$i.sol$C1P1$IC$options$setms) for Intermediate objects (e.g., names(Intermediate_2016$i.sol$C1P1$IC$options$setms)). 

Well, I realized that's not true and it depends on the complexity of the solutions' structure (no pun intended) that can happen in every object derived from the minimization of the truth table. In the example at the end (do not mind about Complex and Intermediate being the same), I have a set of Parsimonious solutions that are quite complex (again, no pun intended) and I could not find anywhere the list of solutions proposed as in the other objects.

Therefore, my questions are: 
1) Is there a way to retrieve the solutions' list and relative stats (i.e., inclS, PRI, covS, covU) regardless from the complexity of the nested structure of the object (i.e., regardless than one or more Ms are generated)? 
2) When only M1is detected the path for all solutions is object$essential for Complex and Parsimonious objects? 
3)  When more than one M is detected is the path always names(OBJECTNAME$i.sol$C1P1$IC$options$setms)?
4) Regardless from the complexity of the solutions (only M1 or more Ms), for Intermediate object is the path always names(OBJECTNAME$i.sol$C1P1$IC$options$setms) ?

Complex_2016 <- minimize(results, details = TRUE)
Intermediate_2016 <- minimize(results, include = "?", details = TRUE, dir.exp = directional_expectations)
Parsimonious_2016 <- minimize(results, include = "?", details = TRUE)

Complex_2016 

M1: ~A*D*~E*~G + B*C*D*~E*~G + ~C*D*~E*~F*~G + ~A*~B*~C*~E*~F*~G + ~A*B*~C*D*~F*~G -> Y

                      inclS   PRI   covS   covU  
------------------------------------------------
1         ~A*D*~E*~G  0.848  0.767  0.636  0.200
2        B*C*D*~E*~G  0.864  0.801  0.150  0.044
3      ~C*D*~E*~F*~G  0.846  0.773  0.388  0.058
4  ~A*~B*~C*~E*~F*~G  0.856  0.779  0.242  0.026
5    ~A*B*~C*D*~F*~G  0.815  0.742  0.136  0.022
------------------------------------------------
                  M1  0.845  0.767  0.786 

Complex_2016$essential
[1] "~A*D*~E*~G"        "B*C*D*~E*~G"       "~C*D*~E*~F*~G"     "~A*~B*~C*~E*~F*~G" "~A*B*~C*D*~F*~G"  

Intermediate_2016

From C1P1, C1P2, C1P3, C1P4:

M1:    ~A*D*~E*~G + B*C*D*~E*~G + ~C*D*~E*~F*~G + ~A*~B*~C*~E*~F*~G + ~A*B*~C*D*~F*~G -> Y

                      inclS   PRI   covS   covU  
------------------------------------------------
1         ~A*D*~E*~G  0.848  0.767  0.636  0.200
2        B*C*D*~E*~G  0.864  0.801  0.150  0.044
3      ~C*D*~E*~F*~G  0.846  0.773  0.388  0.058
4  ~A*~B*~C*~E*~F*~G  0.856  0.779  0.242  0.026
5    ~A*B*~C*D*~F*~G  0.815  0.742  0.136  0.022
------------------------------------------------
                  M1  0.845  0.767  0.786 

Intermediate_2016$essential
[1] "~F"
names(Intermediate_2016$i.sol$C1P1$IC$options$setms)
[1] "~A*D*~E*~G"        "B*C*D*~E*~G"       "~C*D*~E*~F*~G"     "~A*~B*~C*~E*~F*~G" "~A*B*~C*D*~F*~G"  

Parsimonious_2016 

M1: ~F + (~A*~C + C*D) -> Y
M2: ~F + (~A*D + A*C) -> Y
M3: ~F + (~A*D + B*C) -> Y
M4: ~F + (~A*D + C*D) -> Y

                               ---------------------------------
          inclS   PRI   covS   covU   (M1)   (M2)   (M3)   (M4)  
----------------------------------------------------------------
1     ~F  0.711  0.607  0.676  0.075  0.084  0.123  0.132  0.128
----------------------------------------------------------------
2  ~A*~C  0.713  0.606  0.571  0.004  0.139                      
3   ~A*D  0.714  0.609  0.756  0.000         0.248  0.182  0.136
4    A*C  0.691  0.576  0.079  0.002         0.034              
5    B*C  0.736  0.649  0.190  0.001                0.024        
6    C*D  0.707  0.603  0.304  0.000  0.143                0.030
----------------------------------------------------------------
      M1  0.708  0.601  0.959
      M2  0.709  0.602  0.958
      M3  0.709  0.603  0.948
      M4  0.710  0.604  0.955 



As always, thank you for your time.

Best,
Luigi

Adrian Dușa

unread,
Jan 25, 2024, 8:34:27 AM1/25/24
to QCA with R
Hello Luigi,

There are many questions here, and a (minimal) reproducible example would definitely help, as I don't quite exactly understand what are you looking for.
Just to comment a bit about what I can read, for instance about the "... complexity of the solutions (only M1 or more Ms) ...", that toe me is not complexity but model ambiguity.
When many models are returned, it is said there is a high model ambiguity. When only one model is returned, the ambiguity is at its lowest.

The intermediate solution models are always found in the "i.sol" component of the minimize() object.

The essential PIs are those without which the PI chart cannot be solved. They are the only ones that uniquely cover one particular observed positive configuration. These essential PIs can be found in every QCA solution, be it complex, intermediate or parsimonious. For instance, ~F in your parsimonious solution is an essential PI, found in all four models.

It would help a lot if you could explain what type of problem do you try to resolve. I see that you're looking into the result object, but I don't understand what is your aim.

Best,
Adrian

Luigi Rombi

unread,
Jan 25, 2024, 1:20:32 PM1/25/24
to QCA with R
Dear Adrian,
thank you for your clarification about the taxonomy to be adopted (i.e., ambiguity vs. complexity) and confirming the fact that intermediate solution models are always in the $i.sol path. 

I'll try to explain what is my aim so that, hopefully, it will be more clear. 

I wrote a (very inelegant) script to run several QCA analyses in different years. In this script the idea is to compute, for each year, a truth table that contain at least 80% of the cases, minimize it (by creating three separate objects: Complex, Intermediate and Parsimonious), and transfer the solutions and relative stats (inclS, PRI, covS, covU) into a dataframe. This, for both the outcome (solutions_YEAR) and its negated version (solutionsNEG_year).

In order to have an intuitive output, I am trying to convert the "letter" model into something that is more immediate to understand (something similar to Fiss, 2011, ref at the end) so that the solutions/solutionsNEG dataframe will show full black circles, empty circles and empty space in case of the presence of a configurator, presence of its negated version or its absence, respectively, in a given model.

To do this I created two functions: 
1) compute_stat (rows 93-152): picks solutions' statistics (inclS, PRI, covS, and covU) from the object obtained after that the minimization process have been done; 
2) transform_solution (rows 156-175) transform the model's list into full black circles, empty circles or empty spaces.

Then these function are used in rows 466-472 and 483-505 to populate the solution dataframe for a given year. 

However, here's the path issue. As you clarified that model ambiguity may arise everywhere (i.e., Complex, Intermediate, Parsimonious), I wonder how I could modify the script so that it will adapt, in terms of model ambiguity and relative statistics.

To have a glimpse of what I'd like, I attached the draft of my script and some of my files.

You will notice that for 2018 and 2020, since there is not model ambiguity, the relative solution's dataframes (i.e., solutions_2018 and solutions_2020) correctly display all the solutions and relative stats. However, for the remaining years, as ambiguity arise, the solution's dataframe does not correctly display everything. 

Please, feel free to comment anything on the script. I would really appreciate that.

As always, thank you for your time.

Best,
Luigi


Fiss, P. C. (2011). Building better causal theories: A fuzzy set approach to typologies in organization research. Academy of management journal54(2), 393-420.
File test.zip
Temporal QCA draft.R

Adrian Dușa

unread,
Jan 25, 2024, 3:35:40 PM1/25/24
to QCA with R
Hi Luigi,

I took a quick look into your code, it seems like a very complex project.
It would take me quite some time to figure out exactly what you do there, or where exactly the code does not produce the intended result.

I suspect your code breaks somewhere, and I usually go through the break point and figure out why it broke (at which particular iteration, what input values were there etc.) But in this case I can't do that because you wrote your code using tryCatch() failsafe parts.

The usual way to get past these bottlenecks it to split the problem into its simplest possible parts. Then create a minimal reproducible example, that would help me guide you further.

What you could do is to:
- look into the result objects,
- determine where there should have been some expected output
- instead you find a (catched) error message
- isolate the input values for that particular command
- provide those (and only those) and explain what did you expect to find
- eventually provide other input values that does produce the expected result

All of these should be as minimal as possible. When performing this exercise, the person asking the question usually finds the answer in the process. For me it would be a lot easier to determine what the bottleneck is and further guide you.

Best,
Adrian

Reply all
Reply to author
Forward
0 new messages