snotskie / EpistemicNetworkAnalysis.jl

Native implementation of Epistemic Network Analysis written in the Julia programming language. Based on rENA 0.2.0.1.
https://snotskie.github.io/EpistemicNetworkAnalysis.jl/
GNU General Public License v3.0
5 stars 2 forks source link

Missing Code-wise ENA #10

Open snotskie opened 1 year ago

snotskie commented 1 year ago

Code-wise ENA currently only lives as a script I used for the project with Meixi et al.

In theory it should be simple to reimplement it by creating a codeWise helper that transforms your data before creating your model.

I would like to have a few more use cases for code-wise ENA before doing that though, since it's not clear right now how code-wise models should be done

snotskie commented 10 months ago

copy of the code used previously:

println("Importing libraries...")
using EpistemicNetworkAnalysis
using CSV
using DataFrames
using Plots
using Plots.PlotMeasures
using Colors
using GLM

let

global data
global myENA

println("Loading data...")
filename = "Meixi Data 3.csv"
# filename = "PreK.csv"
data = DataFrame(CSV.File(filename))
# data = ena_dataset("transitions.data")
# derivedAnyCode!(data, :BODY, :Changes, :Mood, :Oily, :Dysphoria, :Cry)
# derivedAnyCode!(data, :REFLECT, :Identity, :Longing, :Dream, :Childhood, :Family, :Name, :Letter, :Doubt, :Religion)
# derivedAnyCode!(data, :LEARN, :WWW, :Experiment, :Recipe)
# derivedAnyCode!(data, :PROGRESS, :Strangers, :Passed, :Out, :Affirmation)

println("Specifying Model...")

windowSize = 7
timeVar = :Row

# windowSize = 3
# timeVar = :Day

# codes = Symbol.([
#     # "PersonalHistory", Too few in story 2
#     "Students",
#     "Society",
#     # "Deficit", # Too few in story 2
#     # "PossibleSelves", # Too few in story 2
#     "Challenge",
#     "Reciprocity",
#     # "Collectivity", # Too few in story 2
#     "Openness",
#     "Apply",
#     "Giving",
# ])

codes = Symbol.([
    # "PersonalHistory", # overlaps with society on the plot
    "Students",
    "Society",
    "Deficit",
    "PossibleSelves",
    "Challenge",
    # "Reciprocity", # occurs the least
    "Collectivity",
    # "Openness", # occurs the least
    # "Apply", # occurs the least
    "Giving",
])

# codes = [
#     :Relationships,
#     :Knowings,
#     :Tellings,
#     :Worldviews,
#     :Values,
#     :Challenges,
#     # :Dare, # too few windows
#     :Excellence,
#     :Reciprocity,
#     :Collectiveness,
#     :Openness,
#     :Apply,
#     :Giving,
#     :Difference
# ]

# windowSize = 4
# timeVar = :RowID
# codes = [
#     # :X1_Science,
#     :Chemistry,
#     :Anatomy,
#     :Zoology,
#     :Astronomy,
#     :Meteorology,
#     :Geology,
#     :Paleontology,
#     :Biology,
#     :Botany,
#     # :X2_Engineering,
#     Symbol("Manufacturing.Engineering"),
#     :Robotics,
#     :Technology,
#     # :X3_Other,
#     :History,
#     :Games
# ]

println("Cleaning data...")
function fix(val)
    if ismissing(val)
        return 0
    elseif val in [1, "1"]
        return 1
    else
        println(val)
        return 0
    end
end

for code in codes
    data[!, code] = fix.(data[!, code])
end

firstStoryRows = data[!, :Story] .== 1
secondStoryRows = data[!, :Story] .== 2

data = copy(data[firstStoryRows, :])
# data = copy(data[secondStoryRows, :])
display(data[!, codes])
# display(data[data[!, :Deficit] .== 1, codes])

# codes = [
#     :BODY,
#     :REFLECT,
#     :LEARN,
#     :PROGRESS,
#     :DoseTracking,
#     :SkippedDose,
#     :Happy,
#     :NonHappy,
#     :Sweets,
# ]

colors = RGB.(range(HSL(colorant"red"), stop=HSL(colorant"green"), length=length(codes)))

println("Reverbing codes...")
polyphonic_units = Symbol[]
for code in codes
    strike = 0
    sound = 0
    unit = nothing # temp
    for (i, val) in enumerate(data[!, code])
        if sound == 0 && val == 1
            strike += 1
            unit = Symbol(string(code, strike))
            push!(polyphonic_units, unit)
            data[!, unit] .= 0
        end

        if val == 1
            sound = windowSize
        elseif sound > 0
            sound -= 1
        end

        if sound > 0
            data[i, unit] = 1
        end
    end
end

polyphonic_data = nothing # temp
for unit in polyphonic_units
    group = Symbol(replace(string(unit), r"[0-9]" => ""))
    rows = data[!, unit] .== 1
    subset = copy(data[rows, :])
    subset[!, :PolyUnit] .= unit
    subset[!, :PolySection] .= unit
    subset[!, :PolyGroup] .= group
    start = findfirst(==(1), data[!, unit])
    start -= windowSize
    if start > 1
        prefix = copy(data[start:start+windowSize, :])
        prefix[!, :PolyUnit] .= "prefix"
        prefix[!, :PolySection] .= unit
        prefix[!, :PolyGroup] .= group
        subset = vcat(prefix, subset)
    end

    if isnothing(polyphonic_data)
        polyphonic_data = subset
    else
        polyphonic_data = vcat(polyphonic_data, subset)
    end
end

display(polyphonic_data)

println("Running ENA...")
conversations = [:PolySection]
units = [:PolyUnit]

function myFilter(row)
    return row[:PolyUnit] != "prefix"
end

rotation = FormulaRotation(
    # y ~ 1 + (time)
    LinearModel, 2, FormulaTerm(Term(:y), ConstantTerm(1) + Term(timeVar)), nothing
)

# rotation = MulticlassRotation(:PolyGroup)

# rotation = SVDRotation()

myENA = ENAModel(
    polyphonic_data, codes, conversations, units,
    sphereNormalize=true,
    dropEmpty=true,
    windowSize=windowSize,
    subsetFilter=myFilter,
    rotateBy=rotation
)

CSV.write("accum.csv", innerjoin(myENA.accumModel, myENA.metadata, on=:ENA_UNIT))
display(myENA)

println("Plotting...")
GR.setarrowsize(1/7) # BUGFIX
p = plot(myENA, groupBy=:PolyGroup, showCIs=false, showNetworks=true, spectralColorBy=timeVar, leg=nothing, showTrajectoryBy=timeVar, margin=20mm, extraColors=colors)
# savefig(p, "plot2.svg")
# savefig(p, "PreK.svg")
savefig(p, "reverberations.svg")
savefig(p, "reverberations.png")

p = plot(myENA, groupBy=:PolyGroup, showCIs=false, showNetworks=true, spectralColorBy=timeVar, leg=nothing, margin=20mm, extraColors=colors)
savefig(p, "reverberations_clean.svg")
savefig(p, "reverberations_clean.png")

println("Done!")

end # let
snotskie commented 10 months ago

im leaning towards doing this as a published example for https://github.com/snotskie/EpistemicNetworkAnalysis.jl/issues/13