根据几个条件创建矩阵列表
Create a list of matrices based on several conditions
假设我有以下数据集:
cntry <-c(1,2,3,4,1,2,3,4,1,2,3,4)
year<-c(1990,1990,1990,1990,1991,1991,1991,1991,1992,1992,1992,1992)
exist<-c(1,1,0,0,1,1,1,0,1,1,1,1)
region<-c(1,2,2,1,1,2,2,1,1,2,2,1)
data<-data.frame(cntry,year,exist,region)
split.data<-split(data,data$year)
$`1990`
cntry year exist region
1 1 1990 1 1
2 2 1990 1 2
3 3 1990 0 2
4 4 1990 0 1
$`1991`
cntry year exist region
5 1 1991 1 1
6 2 1991 1 2
7 3 1991 1 2
8 4 1991 0 1
$`1992`
cntry year exist region
9 1 1992 1 1
10 2 1992 1 2
11 3 1992 1 2
12 4 1992 1 1
cntry:国家,year:观测年份,exist:一个国家是否真实存在,region:这个国家位于哪个地区
对于每一年,我想创建一个矩阵来指示两个国家(当它们都存在时)是否位于同一区域,并且最好也将其存储在列表中。
对于 1991 年,结果将如下所示(只有国家 2 和 3 确实存在并且位于同一地区):
b<-matrix(NA, nrow=length(unique(cntry)), ncol=length(unique(cntry)))
colnames(b)<-unique(cntry)
rownames(b)<-unique(cntry)
for(j in 1:length(split.data$`1991`$cntry)){
for(i in 1:length(split.data$`1991`$cntry)){
if(split.data$`1991`$region[i]==split.data$`1991`$region[j]&split.data$`1991`$exist[i]==1&split.data$`1991`$exist[j]==1){
b[j,i] <- 1
} else{
b[j,i]<-0
}
}
}
diag(b)<-0
所有年份的输出需要如下所示:
b
$`1990`
1 2 3 4
1 0 0 0 0
2 0 0 0 0
3 0 0 0 0
4 0 0 0 0
$`1991`
1 2 3 4
1 0 0 0 0
2 0 0 1 0
3 0 1 0 0
4 0 0 0 0
$`1992`
1 2 3 4
1 0 0 0 1
2 0 0 1 0
3 0 1 0 0
4 1 0 0 0
我努力寻找一种方法来包含年份维度(也用于存储结果)并且我也想知道 for 循环是否真的是解决问题的有效方法。
非常感谢任何意见!
这是一种可能性,输出是一个列表(每年都有命名元素),其中包含 data.frames 的列表,其中国家/地区在同一地区,对于每个地区:
res = lapply(split(data, year), function(u){
df = subset(u, exist==1, select=c("cntry", "region"))
Filter(function(x) nrow(x)>1, split(df, df$region))
})
Filter(function(x) length(x)>0, res)
#$`1991`
#$`1991`$`2`
# cntry region
#6 2 2
#7 3 2
#$`1992`
#$`1992`$`1`
# cntry region
#9 1 1
#12 4 1
#$`1992`$`2`
# cntry region
#10 2 2
#11 3 2
这样:
#> res$'1991'
#$`2`
# cntry region
#6 2 2
#7 3 2
这是一个使用 tcrossprod
的选项。使用 lapply
遍历列表 ("split.data"),对数据集的行进行子集化,其中 "exist" 等于 1 (x$exist==1
),select 列 (c('cntry', 'region')
) 创建 "x1"。将 "cntry" 列更改为 factor 并将级别指定为来自 "data" (factor(x$cntry, levels=lvls)
) 的 "cntry" 的唯一元素,得到 [=22= 的 table
], tcrossprod
输出,并将对角线更改为“0”。删除结果的属性是可选的。
lvls <- unique(data$cntry)
lst <- lapply(split.data, function(x) {
x1 <- x[x$exist==1, c('cntry', 'region')]
x1$cntry <- factor(x1$cntry, levels=lvls)
tbl <- table(x1)
t1 <- tcrossprod(tbl)
diag(t1) <- 0
names(dimnames(t1))<- NULL
t1
})
lst
#$`1990`
# 1 2 3 4
#1 0 0 0 0
#2 0 0 0 0
#3 0 0 0 0
#4 0 0 0 0
#$`1991`
# 1 2 3 4
#1 0 0 0 0
#2 0 0 1 0
#3 0 1 0 0
#4 0 0 0 0
#$`1992`
# 1 2 3 4
#1 0 0 0 1
#2 0 0 1 0
#3 0 1 0 0
#4 1 0 0 0
假设我有以下数据集:
cntry <-c(1,2,3,4,1,2,3,4,1,2,3,4)
year<-c(1990,1990,1990,1990,1991,1991,1991,1991,1992,1992,1992,1992)
exist<-c(1,1,0,0,1,1,1,0,1,1,1,1)
region<-c(1,2,2,1,1,2,2,1,1,2,2,1)
data<-data.frame(cntry,year,exist,region)
split.data<-split(data,data$year)
$`1990`
cntry year exist region
1 1 1990 1 1
2 2 1990 1 2
3 3 1990 0 2
4 4 1990 0 1
$`1991`
cntry year exist region
5 1 1991 1 1
6 2 1991 1 2
7 3 1991 1 2
8 4 1991 0 1
$`1992`
cntry year exist region
9 1 1992 1 1
10 2 1992 1 2
11 3 1992 1 2
12 4 1992 1 1
cntry:国家,year:观测年份,exist:一个国家是否真实存在,region:这个国家位于哪个地区
对于每一年,我想创建一个矩阵来指示两个国家(当它们都存在时)是否位于同一区域,并且最好也将其存储在列表中。
对于 1991 年,结果将如下所示(只有国家 2 和 3 确实存在并且位于同一地区):
b<-matrix(NA, nrow=length(unique(cntry)), ncol=length(unique(cntry)))
colnames(b)<-unique(cntry)
rownames(b)<-unique(cntry)
for(j in 1:length(split.data$`1991`$cntry)){
for(i in 1:length(split.data$`1991`$cntry)){
if(split.data$`1991`$region[i]==split.data$`1991`$region[j]&split.data$`1991`$exist[i]==1&split.data$`1991`$exist[j]==1){
b[j,i] <- 1
} else{
b[j,i]<-0
}
}
}
diag(b)<-0
所有年份的输出需要如下所示:
b
$`1990`
1 2 3 4
1 0 0 0 0
2 0 0 0 0
3 0 0 0 0
4 0 0 0 0
$`1991`
1 2 3 4
1 0 0 0 0
2 0 0 1 0
3 0 1 0 0
4 0 0 0 0
$`1992`
1 2 3 4
1 0 0 0 1
2 0 0 1 0
3 0 1 0 0
4 1 0 0 0
我努力寻找一种方法来包含年份维度(也用于存储结果)并且我也想知道 for 循环是否真的是解决问题的有效方法。
非常感谢任何意见!
这是一种可能性,输出是一个列表(每年都有命名元素),其中包含 data.frames 的列表,其中国家/地区在同一地区,对于每个地区:
res = lapply(split(data, year), function(u){
df = subset(u, exist==1, select=c("cntry", "region"))
Filter(function(x) nrow(x)>1, split(df, df$region))
})
Filter(function(x) length(x)>0, res)
#$`1991`
#$`1991`$`2`
# cntry region
#6 2 2
#7 3 2
#$`1992`
#$`1992`$`1`
# cntry region
#9 1 1
#12 4 1
#$`1992`$`2`
# cntry region
#10 2 2
#11 3 2
这样:
#> res$'1991'
#$`2`
# cntry region
#6 2 2
#7 3 2
这是一个使用 tcrossprod
的选项。使用 lapply
遍历列表 ("split.data"),对数据集的行进行子集化,其中 "exist" 等于 1 (x$exist==1
),select 列 (c('cntry', 'region')
) 创建 "x1"。将 "cntry" 列更改为 factor 并将级别指定为来自 "data" (factor(x$cntry, levels=lvls)
) 的 "cntry" 的唯一元素,得到 [=22= 的 table
], tcrossprod
输出,并将对角线更改为“0”。删除结果的属性是可选的。
lvls <- unique(data$cntry)
lst <- lapply(split.data, function(x) {
x1 <- x[x$exist==1, c('cntry', 'region')]
x1$cntry <- factor(x1$cntry, levels=lvls)
tbl <- table(x1)
t1 <- tcrossprod(tbl)
diag(t1) <- 0
names(dimnames(t1))<- NULL
t1
})
lst
#$`1990`
# 1 2 3 4
#1 0 0 0 0
#2 0 0 0 0
#3 0 0 0 0
#4 0 0 0 0
#$`1991`
# 1 2 3 4
#1 0 0 0 0
#2 0 0 1 0
#3 0 1 0 0
#4 0 0 0 0
#$`1992`
# 1 2 3 4
#1 0 0 0 1
#2 0 0 1 0
#3 0 1 0 0
#4 1 0 0 0