将行与列连接起来以创建垂直表

时间:2019-02-12 20:21:36

标签: r dataframe

我试图弄清楚如何连接2个数据帧以创建数据的垂直表。这是一些示例数据:

people <- data.frame(person = c("John","David","Peter"), company = c("A", "B", "C"))
grades <- data.frame(person1=c(10, 40, 50, 60), person2=c(60,70,80, 100), person3=c(33,44,55, 75))

注意:grades中的列顺序与person数据框中的people列的顺序相同。

我想得到一个像下面这样的数据框,但是不知道如何到达那里。希望使用基于R的解决方案(因为我使用的是R的较旧版本,因此某些软件包对我不起作用):

person | company | grade
-------------------------
 John  |    A    | 10
 John  |    A    | 40
 John  |    A    | 50
 John  |    A    | 60
David  |    B    | 60
David  |    B    | 70
David  |    B    | 80
David  |    B    | 100
Peter  |    C    | 33
Peter  |    C    | 44
Peter  |    C    | 55
Peter  |    C    | 75

2 个答案:

答案 0 :(得分:4)

我们将“人”列的“等级”列名称从“人” gather更改为“长”格式,然后执行left_join

library(tidyverse)
setNames(grades, people$person) %>% 
     gather(person, grade) %>% 
    left_join(people)
#   person grade company
#1    John    10       A
#2    John    40       A
#3    John    50       A
#4    John    60       A
#5   David    60       B
#6   David    70       B
#7   David    80       B
#8   David   100       B
#9   Peter    33       C
#10  Peter    44       C
#11  Peter    55       C
#12  Peter    75       C

或将base Rmerge一起使用

merge(stack(setNames(grades, people$person)), 
      people, all.x = TRUE, by.x = 'ind', by.y = 'person')

答案 1 :(得分:2)

使用cbind的基本R选项为

idx <- rep(seq_along(people$person), each = dim(grades)[1])
cbind(people[idx,], stack(unlist(grades))["values"])

结果

#    person company values
#1     John       A     10
#1.1   John       A     40
#1.2   John       A     50
#1.3   John       A     60
#2    David       B     60
#2.1  David       B     70
#2.2  David       B     80
#2.3  David       B    100
#3    Peter       C     33
#3.1  Peter       C     44
#3.2  Peter       C     55
#3.3  Peter       C     75

unlist上使用stackgrades来获得

stack(unlist(grades))
   values          ind
1      10 john_grades1
2      40 john_grades2
3      50 john_grades3
4      60 john_grades4
5      60       david1
6      70       david2
7      80       david3
8     100       david4
9      33          pj1
10     44          pj2
11     55          pj3
12     75          pj4

因为“等级中列的顺序与人员数据框中人员列的顺序相同。”在扩展cbind使其具有正确的行数之后,接下来可以使用people

(idx <- rep(seq_along(people$person), each = dim(grades)[1]))
# [1] 1 1 1 1 2 2 2 2 3 3 3 3

另一种选择,可能会更快一点

cbind(people[idx,], data.frame(grade = unlist(grades, use.names = FALSE)))