Here is a simple solution that uses base R.
# Dummy data
df6 <- data.frame(
id = c(1, 2, 3),
v1 = c(0, 2, 0),
v2 = c(0, 0, 1),
v3 = c(3, 0, 0)
)
df_yummy <- data.frame(
VarId = c("v1", "v2", "v3"),
VarName = c("Apple", "Lemon", "Peach"),
Yummyness = c(2, 1, 3)
)
df6$VarId <- names(df6[-1])[apply(X = df6[-1] > 0, MARGIN = 1, FUN = which)]
df_result <- merge(df6, df_yummy)[, c("id", "VarName", "Yummyness")]
names(df_result) <- c("id", "Fruit", "Yummyness")
> df_result[order(df_result$id), ]
id Fruit Yummyness
3 1 Peach 3
1 2 Apple 2
2 3 Lemon 1
The crux of this solution is found in apply(X = df6[-1] > 0, MARGIN = 1, FUN = which)
. What this does is take your df6
and removes the first column (the [-1]
) portion and then finds which records are greater than zero. We then use the apply
function to apply the which
function over the rows (the MARGIN = 1) portion. This means that for every row, we are returning the index which is non-zero. We pass this to names()
to get the right name for each, and then the rest is just some joins.
Here's a slightly more compact version that uses the data.table
package.
library(data.table)
# Dummy data
df6 <- data.table(
id = c(1, 2, 3),
v1 = c(0, 2, 0),
v2 = c(0, 0, 1),
v3 = c(3, 0, 0)
)
df_yummy <- data.table(
VarId = c("v1", "v2", "v3"),
VarName = c("Apple", "Lemon", "Peach"),
Yummyness = c(2, 1, 3)
)
df6[, VarId := names(df6)[-1][which(.SD > 0)], by = id]
df_result <- merge(df6, df_yummy)[order(id), list(id, Fruit = VarName, Yummyness)]
This operates on much the same principle; we use the which
function on the data.table
specific .SD
, by id
, and then use this to pick the right name. This ends up slightly more compact because of the DT syntax but isn't fundamentally all that different.