我需要使用另一个矩阵作为标识符(ID.MA)用长数据帧(DF)填充矩阵(MA)。
我的三个矩阵的想法: MA.ID创建一个标识符,在大DF中查找所需的变量:
a b c
a ID.aa ID.ab ID.ac
b ID.ba ID.bb ID.bc
c ID.ca ID.cb ID.cc
原始的大数据框有无用的信息,但也有一些对我填充目标MA矩阵有用的行:
ID 1990 1991 1992
ID.aa 10 11 12
ID.ab 13 14 15
ID.ac 16 17 18
ID.ba 19 20 21
ID.bb 22 23 24
ID.bc 25 26 27
ID.ca 28 29 30
ID.cb 31 32 33
ID.cc 34 35 36
ID.xx 40 40 55
ID.xy 50 51 45
....
MA应该填充交叉信息。在我的例子中,它应该看起来像DF的一个选定的列(假设,1990):
a b c
a 10 13 16
b 19 22 25
c 28 31 34
我尝试过使用匹配但老实说它没有用完:
MA$a = DF[match(MA.ID$a, DF$ID),2]
我被建议使用data.table
包,但我看不出这对我有什么帮助。
任何人都有办法解决这个问题吗?
答案 0 :(得分:2)
假设您的输入是 dataframes ,那么您可以执行以下操作:
library(data.table)
setDT(ma)[, lapply(.SD, function(x) x = unlist(df[match(x,df$ID), "1990"]))
, .SDcols = colnames(ma)]
返回:
a b c
1: 10 13 16
2: 19 22 25
3: 28 31 34
解释:
setDT(ma)
将数据框转换为数据表(这是一个增强的数据框)。.SDcols=colnames(ma)
指定必须应用转换的列。lapply(.SD, function(x) x = unlist(df[match(x,df$ID),"1990"]))
对使用.SDcols
指定的每个列执行匹配操作。使用data.table
的替代方法是首先将ma
转换为长 data.table :
ma2 <- melt(setDT(ma), measure.vars = c("a","b","c"))
setkey(ma2, value) # set key by which 'ma' has to be indexed
setDT(df, key="ID") # transform to a datatable & set key by which 'df' has to be indexed
# joining the values of the 1990 column of df into
# the right place in the value column of 'ma'
ma2[df, value := `1990`]
给出:
> ma2
variable value
1: a 10
2: b 13
3: c 16
4: a 19
5: b 22
6: c 25
7: a 28
8: b 31
9: c 34
此方法的唯一缺点是“值”列中的数值存储为字符值。您可以通过如下扩展来更正此问题:
ma2[df, value := `1990`][, value := as.numeric(value)]
如果您想将其更改回宽屏格式,可以使用rowid
中的dcast
功能:
ma3 <- dcast(ma2, rowid(variable) ~ variable, value.var = "value")[, variable := NULL]
给出:
> ma3
a b c
1: 10 13 16
2: 19 22 25
3: 28 31 34
使用过的数据:
ma <- structure(list(a = structure(1:3, .Label = c("ID.aa", "ID.ba", "ID.ca"), class = "factor"),
b = structure(1:3, .Label = c("ID.ab", "ID.bb", "ID.cb"), class = "factor"),
c = structure(1:3, .Label = c("ID.ac", "ID.bc", "ID.cc"), class = "factor")),
.Names = c("a", "b", "c"), class = "data.frame", row.names = c(NA, -3L))
df <- structure(list(ID = structure(1:9, .Label = c("ID.aa", "ID.ab", "ID.ac", "ID.ba", "ID.bb", "ID.bc", "ID.ca", "ID.cb", "ID.cc"), class = "factor"),
`1990` = c(10L, 13L, 16L, 19L, 22L, 25L, 28L, 31L, 34L),
`1991` = c(11L, 14L, 17L, 20L, 23L, 26L, 29L, 32L, 35L),
`1992` = c(12L, 15L, 18L, 21L, 24L, 27L, 30L, 33L, 36L)),
.Names = c("ID", "1990", "1991", "1992"), class = "data.frame", row.names = c(NA, -9L))
答案 1 :(得分:2)
在基础R中,它可以被视为outer
的作业:
> outer(1:nrow(MA.ID), 1:ncol(MA.ID), Vectorize(function(x,y) {DF[which(DF$ID==MA.ID[x,y]),'1990']}))
[,1] [,2] [,3]
[1,] 10 13 16
[2,] 19 22 25
[3,] 28 31 34
说明:
outer
创建一个矩阵作为第一个参数X
(此处为a b c
)和第二个参数Y
的外部产品(此处为a b c
})X
和Y
的每个组合,它会应用一个函数来查找DF
中ID
所在行MA.ID[X,Y]
中的值},并在列1990
Vectorize
包装函数,因为outer
需要向量化函数或者,另一种方法(仍在基础R中)是:
MA.ID
转换为向量sapply
一个快速查找与DF$ID
这有效:
> structure(
sapply(unlist(MA.ID),
function(id){DF[which(DF$ID==id),'1990']}),
dim=dim(MA.ID), names=NULL)
[,1] [,2] [,3]
[1,] 10 13 16
[2,] 19 22 25
[3,] 28 31 34
(这里对structure(..., dim=dim(MA.ID), names=NULL)
的调用将向量转换回矩阵)