Posting an attempt of a more general function, though it’s much slower than Douglass:
function reshape_long(df, id, cons, stubs)
stub_len = length(stubs);
df_vector = [DataFrame() for _ in 1:stub_len];
iter = 1
for i in 1:length(df_vector)
if iter ==1
df_vector[i] = select(df, [id, cons], Regex(stubs[i]))
iter += 1
else
df_vector[i] = select(df, [id], Regex(stubs[i]))
end
end
df_vector2 = [DataFrame() for _ in 1:stub_len];
for i in 1:length(df_vector2)
df_vector2[i] = stack(df_vector[i], variable_name = stubs[i], Regex(stubs[i]), value_name = Symbol("value_$i") );
df_vector2[i] = combine(groupby(df_vector2[i], id), sdf -> sort(sdf), id => eachindex => :index)
end
res = [DataFrame() for _ in 1:(stub_len-1)];
iter = 1
for i in 1:length(res)
if iter ==1
res[i] = outerjoin(df_vector2[i],df_vector2[i+1], on = [id,:index] )
iter +=1
else
res[i] = outerjoin(res[1], df_vector2[i+1], on = [id, :index])
end
end
d = res[end]
symbs = Symbol(stubs[1])
d[!, symbs] = getproperty.(match.(r"[0-9]+",d[!, symbs]), :match)
rename!(d,symbs => :year)
select!(d, Not([ Symbol(stubs[i]) for i in 2:length(stubs) ]))
rename!(d, [(Symbol("value_$i")=>Symbol(stubs[i])) for i in 1:length(stubs)])
select!(d, Not(:index, ))
return(d)
end
Example: reshape_long(df, :ID, :sex, ["inc", "ue"])