У меня есть этот df1:

A B C
1 2 3
5 7 9

Где A B C - имена столбцов.

У меня есть другой df2 с одним столбцом:

A
1
2
3
4

Я хотел бы добавить df2 для каждого столбца df1, создавая этот окончательный кадр данных:

A B C 
1 2 3
5 7 9
1 1 1
2 2 2
3 3 3
4 4 4

Это возможно сделать?

15
giupardeb 4 Сен 2017 в 23:06

9 ответов

Лучший ответ
data.frame(sapply(df1, c, unlist(df2)), row.names = NULL)
#  A B C
#1 1 2 3
#2 5 7 9
#3 1 1 1
#4 2 2 2
#5 3 3 3
#6 4 4 4

< Сильный > DATA

df1 = structure(list(A = c(1L, 5L), B = c(2L, 7L), C = c(3L, 9L)), .Names = c("A", 
"B", "C"), class = "data.frame", row.names = c(NA, -2L))

df2 = structure(list(A = 1:4), .Names = "A", class = "data.frame", row.names = c(NA, 
-4L))
10
d.b 4 Сен 2017 в 20:24

Вот базовый метод R с rbind, rep и setNames:

rbind(dat, setNames(data.frame(rep(dat1, ncol(dat))), names(dat)))
  A B C
1 1 2 3
2 5 7 9
3 1 1 1
4 2 2 2
5 3 3 3
6 4 4 4

Редактировать: оказывается data.frame не обязательно:

rbind(dat, setNames(rep(dat1, ncol(dat)), names(dat)))

Буду работать.

< Сильный > данные

dat <- 
structure(list(A = c(1L, 5L), B = c(2L, 7L), C = c(3L, 9L)), .Names = c("A", 
"B", "C"), class = "data.frame", row.names = c(NA, -2L))

dat1 <-
structure(list(A = 1:4), .Names = "A", row.names = c(NA, -4L),
class = "data.frame")
7
lmo 4 Сен 2017 в 20:16

Мы можем скопировать df2 для количества столбцов df1, снять его, а затем rbind.

rbind(df1, unname(rep(df2, ncol(df1))))
#   A B C
# 1 1 2 3
# 2 5 7 9
# 3 1 1 1
# 4 2 2 2
# 5 3 3 3
# 6 4 4 4

Данных:

df1 <- structure(list(A = c(1L, 5L), B = c(2L, 7L), C = c(3L, 9L)), .Names = c("A", 
"B", "C"), class = "data.frame", row.names = c(NA, -2L))
df2 <- structure(list(A = 1:4), .Names = "A", row.names = c(NA, -4L), class = "data.frame")
10
Rich Scriven 4 Сен 2017 в 20:14

Я просто люблю R, вот еще одно Base R решение, но с mapply:

data.frame(mapply(c, df1, df2))

< Сильный > Результат :

  A B C
1 1 2 3
2 5 7 9
3 1 1 1
4 2 2 2
5 3 3 3
6 4 4 4

< Сильный > Примечание :

Не нужно иметь дело с именами, как почти во всех других решениях ... Ключ к тому, почему это работает, заключается в том, что mapply вызывает FUN для значений ... [каждого элемента] (повторяется до длины самого длинного ... [элемент] "(см. ?mapply). Другими словами, df2$A рециркулируется во все столбцы df1.

< Сильный > Данные :

df1 = structure(list(A = c(1L, 5L), B = c(2L, 7L), C = c(3L, 9L)), .Names = c("A", 
                                                                               "B", "C"), class = "data.frame", row.names = c(NA, -2L))
df2 = structure(list(A = 1:4), .Names = "A", row.names = c(NA, -4L), class = "data.frame")
7
avid_useR 27 Ноя 2017 в 16:36

Данных:

df1 <- data.frame(A=c(1,5),
                  B=c(2,7),
                  C=c(3,9))
df2 <- data.frame(A=c(1,2,3,4))

Решение:

df2 <- matrix(rep(df2$A, ncol(df1)), ncol=ncol(df1))
colnames(df2) <- colnames(df1)
rbind(df1,df2)

Результат:

  A B C
1 1 2 3
2 5 7 9
3 1 1 1
4 2 2 2
5 3 3 3
6 4 4 4
6
Hack-R 4 Сен 2017 в 20:12

Решение из purrr, которое использует map_dfc для циклического перебора всех столбцов в df1, чтобы объединить все элементы с df2$A.

library(purrr)

map_dfc(df1, ~c(., df2$A))

# A tibble: 6 x 3
      A     B     C
  <int> <int> <int>
1     1     2     3
2     5     7     9
3     1     1     1
4     2     2     2
5     3     3     3
6     4     4     4

Данные

df1 <- structure(list(A = c(1L, 5L), B = c(2L, 7L), C = c(3L, 9L)), .Names = c("A", 
                                                                               "B", "C"), class = "data.frame", row.names = c(NA, -2L))

df2 <- structure(list(A = 1:4), .Names = "A", class = "data.frame",
                 row.names = c(NA, -4L))
5
www 5 Сен 2017 в 03:33

Для полноты, вот data.table подход, который не требует обработки имен столбцов:

library(data.table)
setDT(df1)[, lapply(.SD, c, df2$A)]
   A B C
1: 1 2 3
2: 5 7 9
3: 1 1 1
4: 2 2 2
5: 3 3 3
6: 4 4 4

Обратите внимание, что OP описал df2, чтобы он состоял только из одного столбца.

Существует также базовая версия R этого подхода:

data.frame(lapply(df1, c, df2$A))
  A B C
1 1 2 3
2 5 7 9
3 1 1 1
4 2 2 2
5 3 3 3
6 4 4 4

Это похоже на подход d.b, но не требуется для работы с именами столбцов.

1
Uwe 6 Дек 2017 в 18:02

Мы можем использовать base R методы

rbind(df1, setNames(as.data.frame(do.call(cbind, rep(list(df2$A), 3))), names(df1)))
#  A B C
#1 1 2 3
#2 5 7 9
#3 1 1 1
#4 2 2 2
#5 3 3 3
#6 4 4 4

Данные

df1 <- structure(list(A = c(1L, 5L), B = c(2L, 7L), C = c(3L, 9L)), .Names = c("A", 
"B", "C"), class = "data.frame", row.names = c(NA, -2L))

df2 <- structure(list(A = 1:4), .Names = "A", class = "data.frame",
row.names = c(NA, -4L))
7
akrun 4 Сен 2017 в 20:10

По аналогии с превосходным ответом @ useR Base R, вот tidyverse решение:

library(purrr)

map2_df(df1, df2, c)
  A B C
1 1 2 3
2 5 7 9
3 1 1 1
4 2 2 2
5 3 3 3
6 4 4 4

Вот несколько других (менее желательных) вариантов, когда я впервые ответил на этот вопрос.

library(dplyr)

bind_rows(df1, df2 %>% mutate(B=A, C=A))

Или, если мы хотим динамически получить количество столбцов и их имена из df1:

bind_rows(df1,
          df2[,rep(1,ncol(df1))] %>% setNames(names(df1)))

И еще один метод Base R:

rbind(df1, setNames(df2[,rep(1,ncol(df1))], names(df1)))
5
eipi10 5 Сен 2017 в 15:44