R-создать новую переменную, где каждое наблюдение зависит от другой таблицы и других переменных в фрейме данных
у меня есть две следующие таблицы:
df <- data.frame(eth = c("A","B","B","A","C"),ZIP1 = c(1,1,2,3,5))
Inc <- data.frame(ZIP2 = c(1,2,3,4,5,6,7),A = c(56,98,43,4,90,19,59), B = c(49,10,69,30,10,4,95),C = c(69,2,59,8,17,84,30))
eth ZIP1 ZIP2 A B C
A 1 1 56 49 69
B 1 2 98 10 2
B 2 3 43 69 59
A 3 4 4 30 8
C 5 5 90 10 17
6 19 4 84
7 59 95 39
Я хотел бы создать переменную Inc в фрейме данных df, где для каждого наблюдения значение является пересечением eth и ZIP наблюдения. В моем примере это привело бы к:
eth ZIP1 Inc
A 1 56
B 1 49
B 2 10
A 3 43
C 5 17
цикл или довольно грубая сила могут решить его, но это занимает время в моем наборе данных, я ищу более тонкий способ, возможно, используя данные.таблица. Мне кажется, что это очень стандартный вопрос и я извиняюсь, если это это моя неспособность сформулировать точное название для этой проблемы (как вы, возможно, заметили..) может быть, поэтому я не нашел подобного вопроса в поиске на форуме..
спасибо !
5 ответов
Как насчет этого?
library(reshape2)
merge(df, melt(Inc, id="ZIP2"), by.x = c("ZIP1", "eth"), by.y = c("ZIP2", "variable"))
ZIP1 eth value
1 1 A 56
2 1 B 49
3 2 B 10
4 3 A 43
5 5 C 17
конечно, это можно сделать в данных.таблица:
library(data.table)
setDT(df)
df[ melt(Inc, id.var="ZIP2", variable.name="eth", value.name="Inc"),
Inc := i.Inc
, on=c(ZIP1 = "ZIP2","eth") ]
синтаксис для этой операции "merge-assign" -X[i, Xcol := expression, on=merge_cols]
.
вы можете запустить i = melt(Inc, id.var="ZIP", variable.name="eth", value.name="Inc")
часть сама по себе, чтобы увидеть, как это работает. Внутри слияния столбцы из i
можно сослаться на i.*
префиксы.
поочередно...
setDT(df)
setDT(Inc)
df[, Inc := Inc[.(ZIP1), eth, on="ZIP2", with=FALSE], by=eth]
это построено на аналогичной идее. виньетки пакет являются хорошим местом для начала для такого рода синтаксис.
можно использовать row/column
индексации
df$Inc <- Inc[cbind(match(df$ZIP1, Inc$ZIP2), match(df$eth, colnames(Inc)))]
df
# eth ZIP1 Inc
#1 A 1 56
#2 B 1 49
#3 B 2 10
#4 A 3 43
#5 C 5 17
другой вариант:
library(dplyr)
library(tidyr)
Inc %>%
gather(eth, value, -ZIP2) %>%
left_join(df, ., by = c("eth", "ZIP1" = "ZIP2"))
мое решение (которое, возможно, кажется неудобным)
for (i in 1:length(df$eth)) {
df$Inc[i] <- Inc[as.character(df$eth[i])][df$ZIP[i],]
}