With data.table:
library(data.table)
res = melt(setDT(sample_df),
measure.vars = patterns("^Product", "^Quantity"),
variable.name = "ProductNumber")
res[, ProductNumber := factor(ProductNumber, labels = c("A","B"))]
which gives
clientid ProductNumber value1 value2
1: 1 A chair 1
2: 2 A table 2
3: 3 A plate 1
4: 4 A plate 1
5: 5 A table 1
6: 6 A chair 1
7: 7 A table 2
8: 8 A plate 3
9: 9 A chair 1
10: 10 A chair 2
11: 1 B table 3
12: 2 B doll 1
13: 3 B shoes 2
14: 4 B NA NA
15: 5 B door 2
16: 6 B NA NA
17: 7 B computer 1
18: 8 B computer 1
19: 9 B NA NA
20: 10 B plate 1
Data (since the OP's original data was borked):
structure(list(clientid = 1:10, ProductA = structure(c(1L, 3L,
2L, 2L, 3L, 1L, 3L, 2L, 1L, 1L), .Label = c("chair", "plate",
"table"), class = "factor"), QuantityA = c(1L, 2L, 1L, 1L, 1L,
1L, 2L, 3L, 1L, 2L), ProductB = structure(c(6L, 2L, 5L, NA, 3L,
NA, 1L, 1L, NA, 4L), .Label = c("computer", "doll", "door", "plate",
"shoes", "table"), class = "factor"), QuantityB = c(3L, 1L, 2L,
NA, 2L, NA, 1L, 1L, NA, 1L)), .Names = c("clientid", "ProductA",
"QuantityA", "ProductB", "QuantityB"), row.names = c(NA, -10L
), class = "data.frame")