R умножить неравные кадры данных на основе заданных значений столбцов c - PullRequest
0 голосов
/ 28 февраля 2020

Обновлен вопрос, чтобы включить дополнительные столбцы, которые передаются из df1 в вывод, а также добавить, что основной df имеет 7 миллионов строк.


У меня есть два кадра данных, аналогичные на Pandas SO Вопрос

И мне нужно умножить их там, где имена совпадают. Я не уверен, как сделать это чисто. Есть ли функция применения, которая делает это легко?

DF1: (есть 16 столбцов дополнительных данных, длиной 7 миллионов строк)

Data1   Data2   Name      Value
aa      bb      sample1   50
ff      ff      sample1   100
ef      fd      sample1   75
ff      df      sample2   100
bbf     ad3     sample2   200
dd      a       sample2   300
33      3rf     sample3   25
ddd     dd      sample3   50
dd      dd      sample3   40

DF2:

Name      Value
sample1   1
sample2   0.5
sample3   2

ВЫХОД: (с дополнительными 16 столбцами, которые не показаны)

Data1   Data2   Name      Value
aa      bb      sample1   50
ff      ff      sample1   100
ef      fd      sample1   75
ff      df      sample2   50
bbf     ad3     sample2   100
dd      a       sample2   150
33      3rf     sample3   50
ddd     dd      sample3   100
dd      dd      sample3   80

Ответы [ 4 ]

2 голосов
/ 28 февраля 2020

Мы можем объединить оба кадра данных, используя left_join или inner_join, а затем умножить соответствующие столбцы Value друг на друга. Используя dplyr, это можно сделать как:

library(dplyr)

inner_join(df1, df2, by = 'Name') %>%
   mutate(Value = Value.x * Value.y) %>%
   select(names(df1))

#     Name Value
#1 sample1    50
#2 sample1   100
#3 sample1    75
#4 sample2    50
#5 sample2   100
#6 sample2   150
#7 sample3    50
#8 sample3   100
#9 sample3    80

data

df1 <- structure(list(Name = structure(c(1L, 1L, 1L, 2L, 2L, 2L, 3L, 
3L, 3L), .Label = c("sample1", "sample2", "sample3"), class = "factor"), 
Value = c(50L, 100L, 75L, 100L, 200L, 300L, 25L, 50L, 40L
)), class = "data.frame", row.names = c(NA, -9L))

df2 <- structure(list(Name = structure(1:3, .Label = c("sample1", "sample2", 
"sample3"), class = "factor"), Value = c(1, 0.5, 2)), class = "data.frame", 
row.names = c(NA, -3L))
2 голосов
/ 28 февраля 2020

Наиболее простым было бы использовать match, чтобы получить индексы строк df2 в правильном порядке.

df2$Value[match(df1$Name, df2$Name)] * df1$Value

Вы также можете преобразовать df2 в вектор с именами, основанными на Name колонка. Затем подмножество значений из него, используя столбец Name df1.

df1$Value * setNames(df2$Value, df2$Name)[df1$Name]
1 голос
/ 28 февраля 2020

Вы можете использовать data.table пакет:

library(data.table)
setDT(df1)[setDT(df2), Value_new := Value * i.Value, on = "Name"]

#     Data1  Data2    Name Value Value_new
# 1:     aa     bb sample1    50        50
# 2:     ff     ff sample1   100       100
# 3:     ef     fd sample1    75        75
# 4:     ff     df sample2   100        50
# 5:    bbf    ad3 sample2   200       100
# 6:     dd      a sample2   300       150
# 7:     33    3rf sample3    25        50
# 8:    ddd     dd sample3    50       100
# 9:     dd     dd sample3    40        80
1 голос
/ 28 февраля 2020

Вы можете попробовать приведенный ниже базовый код R, используя merge

DF1$Value <- do.call(`*`,merge(DF1[c("Name","Value")],DF2,all = TRUE,by="Name")[-1])

, такой что

> DF1
  Data1 Data2    Name Value
1    aa    bb sample1    50
2    ff    ff sample1   100
3    ef    fd sample1    75
4    ff    df sample2    50
5   bbf   ad3 sample2   100
6    dd     a sample2   150
7    33   3rf sample3    50
8   ddd    dd sample3   100
9    dd    dd sample3    80

DATA

DF1 <- structure(list(Data1 = c("aa", "ff", "ef", "ff", "bbf", "dd", 
"33", "ddd", "dd"), Data2 = c("bb", "ff", "fd", "df", "ad3", 
"a", "3rf", "dd", "dd"), Name = c("sample1", "sample1", "sample1", 
"sample2", "sample2", "sample2", "sample3", "sample3", "sample3"
), Value = c(50L, 100L, 75L, 100L, 200L, 300L, 25L, 50L, 40L)), class = "data.frame", row.names = c(NA, 
-9L))

DF2 <- structure(list(Name = c("sample1", "sample2", "sample3"), Value = c(1, 
0.5, 2)), class = "data.frame", row.names = c(NA, -3L))
...