R 在两个数据帧的多列之间匹配数据以返回;匹配的;基于一个或两个匹配列的值或平均值

R 在两个数据帧的多列之间匹配数据以返回;匹配的;基于一个或两个匹配列的值或平均值,r,R,我有一个复杂的问题,不知道如何进行。我有两个名为df1的数据帧: structure(list(State = structure(1:2, .Label = c("Aaa", "Dd"), class = "factor"), City = structure(1:2, .Label = c("bb", "e"), class = "factor"), Type1 = c(NA, NA), Type2 = c(NA, NA)), .Names = c("State", "City", "

我有一个复杂的问题,不知道如何进行。我有两个名为
df1
的数据帧:

structure(list(State = structure(1:2, .Label = c("Aaa", "Dd"), class = "factor"), 
City = structure(1:2, .Label = c("bb", "e"), class = "factor"), 
Type1 = c(NA, NA), Type2 = c(NA, NA)), .Names = c("State", 
"City", "Type1", "Type2"), class = "data.frame", row.names = c(NA, 
-2L))
df2

structure(list(state = structure(c(1L, 1L, 1L, 2L, 2L, 2L, 2L
), .Label = c("Aaa", "Dd"), class = "factor"), city = structure(c(1L, 
2L, 3L, 4L, 4L, 5L, 6L), .Label = c("bb", "ccc", "ddd", "fff", 
"ggg", "hh"), class = "factor"), type = structure(c(1L, 2L, 2L, 
2L, 2L, 2L, 3L), .Label = c("Type 1", "Type 2", "Type 4"), class = "factor"), 
value = 1:7), .Names = c("state", "city", "type", "value"
), class = "data.frame", row.names = c(NA, -7L))
数据帧df1看起来像:

State City Type1 Type2
Aaa   bb    NA    NA
Dd    e    NA    NA
state city   type value
Aaa   bb Type 1     1
Aaa  ccc Type 2     2
Aaa  ddd Type 2     3
Dd  fff Type 2     4
Dd  fff Type 2     5
Dd  ggg Type 2     6
Dd   hh Type 4     7
数据帧df2看起来像:

State City Type1 Type2
Aaa   bb    NA    NA
Dd    e    NA    NA
state city   type value
Aaa   bb Type 1     1
Aaa  ccc Type 2     2
Aaa  ddd Type 2     3
Dd  fff Type 2     4
Dd  fff Type 2     5
Dd  ggg Type 2     6
Dd   hh Type 4     7
对于
df1
中的
NA
,我需要根据以下规则从
df2
中查找值:

1) 如果对于
df2
中的给定
类型
只有一个单个实例,其中
状态
城市
,请将
插入相应的
df1
Type1
Type2

2) 当存在多个实例时,对于给定的
类型
,我需要平均所有
,并将其插入
df1

3) 如果对于给定的
类型
没有
状态
=
状态
城市
=
的实例,我需要获得该
类型
的所有
状态
的平均值,并插入
df1

4) 如果对于给定的
类型
,没有
状态
=
状态
的实例,则该值应保留在
df1
中的
NA

只是澄清一下——本质上,我试图将
Type1
Type2
的平均值尽可能地“解析”。换句话说,如果可能的话,我想使用
城市
级别的平均值,但是如果不可能,那么我想使用
级别的平均值。但是,我想返回
df1
中概述的原始
城市
的这些平均值(即使
平均值是可用的

我知道这很复杂!我想得到的结果是

structure(list(State = structure(1:2, .Label = c("Aaa", "Dd"), class = "factor"), 
City = structure(1:2, .Label = c("bb", "e"), class = "factor"), 
Type1 = c(1L, NA), Type2 = c(2.5, 5)), .Names = c("State", 
"City", "Type1", "Type2"), class = "data.frame", row.names = c(NA, 
-2L))
这是一个数据帧,类似于:

State City Type1 Type2
Aaa   bb     1   2.5
Dd    e    NA   5.0
我甚至不知道从哪里开始解决这个问题。我的第一个想法是我需要使用
acast
来重塑
df2
。例如,我可以使用

acast(df2, state+city+value~type)
这使数据更接近于
df1
,但随后我失去了一些需要保留的列(这些列被压缩到行名中)。我甚至不知道如何开始搜索
City
State
,然后根据这些结果进行平均

谁能给我指出正确的方向吗

编辑(2015年1月):我在下面特洛伊的回答下面添加了一条新评论,询问是否有一种简单的方法可以添加一个列,确定计算平均值的级别(城市或州)。我找到了一个解决方案,尽管可能有更好的方法,但对我来说很有效。希望这对某人有所帮助

getlevel<-function(state,city,type){
m<-means[means$state==state & means$city==city & means$type==type, "mean"]
sm<-state_means[state_means$state==state & state_means$type==type, "mean"]
ifelse(length(m)>0,"city","state")
}

编辑-抱歉误读了问题:以下是针对您的情况的更正代码:

require(plyr)
means<-ddply(df2,.(state,city,type),summarize,mean=mean(value))
state_means<-ddply(df2,.(state,type),summarize,mean=mean(value))
getval<-function(state,city,type){
  m<-means[means$state==state & means$city==city & means$type==type, "mean"]
  sm<-state_means[state_means$state==state & state_means$type==type, "mean"]
  ifelse(length(m)>0,m,sm)
}
## this gives you the new df1
ddply(df1,.(State,City),transform,Type1=getval(as.character(State),as.character(City),"Type 1"),Type2=getval(as.character(State),as.character(City),"Type 2"))

编辑-抱歉误读了问题:以下是针对您的情况的更正代码:

require(plyr)
means<-ddply(df2,.(state,city,type),summarize,mean=mean(value))
state_means<-ddply(df2,.(state,type),summarize,mean=mean(value))
getval<-function(state,city,type){
  m<-means[means$state==state & means$city==city & means$type==type, "mean"]
  sm<-state_means[state_means$state==state & state_means$type==type, "mean"]
  ifelse(length(m)>0,m,sm)
}
## this gives you the new df1
ddply(df1,.(State,City),transform,Type1=getval(as.character(State),as.character(City),"Type 1"),Type2=getval(as.character(State),as.character(City),"Type 2"))

首先重塑df2中的数据,然后使用
data.table
的键适当合并数据:

library(data.table)
library(reshape2)

dt1 <- as.data.table(df1)
dt2 <- as.data.table(df2)
接下来,设置
,以便合并 最后,合并并取平均值,剔除
NA
s
备选方案,基于评论(无“城市”汇总)
dt2.casted首先重塑df2中的数据,然后使用
data.table
的键适当合并数据:

library(data.table)
library(reshape2)

dt1 <- as.data.table(df1)
dt2 <- as.data.table(df2)
接下来,设置
,以便合并 最后,合并并取平均值,剔除
NA
s
备选方案,基于评论(无“城市”汇总)
dt2.casted注意(1)是(2)的特例,所以你可以忽略(1)并执行(2)伟大的点李嘉图,我甚至没有想到这个!=)注意(1)是(2)的特例,所以你可以忽略(1)并执行(2)伟大的点李嘉图,我甚至没有想到这个!=)亲爱的特洛伊,非常感谢你提供了非常翔实的答案。答案为“1”,但对于第一行中的类型2,答案应为2.5(即状态Aaa的类型2平均值=(2+3)/2=2.5)。同样,对于底行的Type2,它应该是状态Dd=(4+5+6)/3=5的所有Type2的平均值。有没有办法在你的解决方案中包含这个平均值?对不起,我对条件的误读。亲爱的特洛伊,我对你的帮助感激不尽。这很有道理,是一个非常优雅的解决方案。我希望我更了解r,这样我就可以立即看到这样的解决方案!现在在我的海量数据集上试试这个-再次感谢!此外,我忽略了一个事实,即我的一个“type”值是“corn”和“wheat”之类的字符串,而不是我的示例中使用的数字。我相信这最终会带来某种错误。我将不得不考虑如何处理这件事。。。对于每个城市,我只有一个字符串,但在州一级工作时,我可能会有一些带有“玉米”的字符串,还有一些带有“小麦”的字符串,我显然无法理解这些字符串的平均值。也许最好只使用出现次数更多的更常见字符串,但我不确定在现有代码中如何做到这一点。特洛伊,在我的较大数据集上使用此字符串时,我得到一个错误“in is.na(e1)| is.na(e2):较长的对象长度不是较短对象长度的倍数2:in
=.default
(state\u表示$state,state):”亲爱的特洛伊,非常感谢你提供了非常翔实的答案。答案为“1”,但对于第一行中的类型2,答案应为2.5(即状态Aaa的类型2平均值=(2+3)/2=2.5)。同样,对于底行的Type2,它应该是状态Dd=(4+5+6)/3=5的所有Type2的平均值。有没有办法在你的解决方案中包含这个平均值?对不起,我对条件的误读。信息技术
setkey(dt2.casted, state, city)
setkey(dt1, State, City)
dt1[dt2.casted][, lapply(.SD, mean, na.rm=TRUE), by=State, .SDcols=grep("Type", names(dt2.casted), value=TRUE)]

   State Type 1 Type 2 Type 4
1:   Aaa      1   2.50    NaN
2:    Dd    NaN   5.25      7
dt2.casted <- reshape2::dcast(dt2, state ~ type
                              , fill=NA_real_
                              , fun.aggregate=mean, na.rm=TRUE)
dt2.casted <- as.data.table(dt2.casted)

setkey(dt2.casted, state)
setkey(dt1, State)

dt1[dt2.casted][, lapply(.SD, mean, na.rm=TRUE)
                , by=list(State, City)
                , .SDcols=grep("Type"
                , names(dt2.casted), value=TRUE)
                ]

   State City Type 1 Type 2 Type 4
1:   Aaa   bb      1    2.5    NaN
2:    Dd    e    NaN    5.0      7