使用R中另一个数据框中的值在一个数据框中创建新变量

时间:2019-12-09 13:14:25

标签: r

我有两个数据集df和df1

df = data.frame(Name = c('A','B','C'),
                Filter = c('D','E','F'),
                Sub_A = c(6,7,8),
                Sub_B = c(9,10,11))

df1 = data.frame(Name = c('A','A','A','A','B','B','B','B','C','C','C','C','P','P','P','P'),
                 Filter = c('D','D','D','X','E','E','E','X','F','F','F','X','Y','Y','Y','Y'),
                 Subject = c('Sub_A','Sub_B','Sub_A','Sub_B','Sub_A','Sub_B','Sub_A','Sub_B','Sub_A','Sub_B','Sub_A','Sub_B','Sub_A','Sub_B','Sub_A','Sub_B'),
                 Marks = c(10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25))

使用针对df数据集中的名称的过滤器我想首先过滤df1数据集中的名称,并使用针对df数据集的Sub_A和Sub_B的值,通过在df1数据集中创建新变量Corrected_Marks来校正Sub_A和Sub_B的df1数据集中的标记。

输出数据集应类似于

Ouput = data.frame(Name = c('A','A','A','B','B','B','C','C','C'),
                   Filter = c('D','D','D','E','E','E','F','F','F'),
                   Subject = c('Sub_A','Sub_B','Sub_A','Sub_A','Sub_B','Sub_A','Sub_A','Sub_B','Sub_A'),
                   Marks = c(10,11,12,14,15,16,18,19,20),
                   Corrected_Marks = c(6.2,10.23,7.44,8.12,13.95,9.28,10.152,17.67,11.28))

2 个答案:

答案 0 :(得分:0)

计算不清楚。也许我们可以在将第一个数据重塑为“长”格式后进行连接,然后进行计算

library(dplyr)
library(tidyr) # >= 1.0.0
df %>%
    pivot_longer(cols = Sub_A:Sub_B, names_to = "Subject",
           values_to = "Corrected_Marks") %>% 
    # for tidyr < 1.0.0
    # gather(Subject, Corrected_Marks, Sub_A:Sub_B) %>%
    inner_join(df1, by = c("Name", "Filter",  "Subject")) %>% 
    mutate(Corrected_Marks = Marks * Corrected_Marks)
# A tibble: 9 x 5
#  Name  Filter Subject Corrected_Marks Marks
#  <chr> <chr>  <chr>             <dbl> <dbl>
#1 A     D      Sub_A                60    10
#2 A     D      Sub_A                72    12
#3 A     D      Sub_B                99    11
#4 B     E      Sub_A                98    14
#5 B     E      Sub_A               112    16
#6 B     E      Sub_B               150    15
#7 C     F      Sub_A               144    18
#8 C     F      Sub_A               160    20
#9 C     F      Sub_B               209    19

答案 1 :(得分:0)

除了@akrun的解决方案之外,还有base R的另一种解决方案,因此不需要其他程序包即可运行以下代码:

dfm <- merge(df,df1)
Ouput <- cbind(dfm[names(df1)],
               Corrected_Marks = apply(dfm, 1, function(x) as.numeric(x["Marks"])*as.numeric(x[x["Subject"]])))

如此

  Name Filter Subject Marks Corrected_Marks
1    A      D   Sub_A    10              60
2    A      D   Sub_B    11              99
3    A      D   Sub_A    12              72
4    B      E   Sub_A    14              98
5    B      E   Sub_B    15             150
6    B      E   Sub_A    16             112
7    C      F   Sub_A    18             144
8    C      F   Sub_B    19             209
9    C      F   Sub_A    20             160

请注意,Subject中的列MarksOuput的元素顺序与df1中的元素顺序相同,这与解决方案中的样子不同@akrun