Мы можем использовать
library(zoo)
df2 <- transform(stack(df1),
ind = na.locf0(replace(ind, grepl('---', ind), NA)))
lst1 <- split(df2$values, as.character(df2$ind))
out <- do.call(cbind, lapply(lst1, `length<-`, max(lengths(lst1))))
out
# Name1 Name2 Name3 Name4
#[1,] "Topic1" "Topic4" "Topic7" "Topic10"
#[2,] "Topic2" "Topic5" "Topic8" NA
#[3,] "Topic3" "Topic6" "Topic9" NA
Или другой вариант - преобразовать в «длинный» формат и затем преобразовать обратно в «широкий» формат
library(dplyr)
library(tidyr)
library(data.table)
df1 %>%
pivot_longer(everything()) %>%
mutate(name = na_if(name, "---")) %>%
fill(name) %>%
mutate(rn = rowid(name)) %>%
select(name, value, rn) %>%
pivot_wider(names_from = name, values_from = value) %>%
select(-rn)
# A tibble: 3 x 4
# Name1 Name2 Name3 Name4
# <chr> <chr> <chr> <chr>
#1 Topic1 Topic4 Topic7 Topic10
#2 Topic2 Topic5 Topic8 <NA>
#3 Topic3 Topic6 Topic9 <NA>
data
df1 <- structure(list(Name1 = "Topic1", `---` = "Topic2", `---` = "Topic3",
Name2 = "Topic4", `---` = "Topic5", `---` = "Topic6", Name3 = "Topic7",
`---` = "Topic8", `---` = "Topic9", Name4 = "Topic10"), row.names = c(NA,
-1L), class = "data.frame")