简体   繁体   English

R 循环或申请从数据框或列表中提取矩阵

[英]R loop or apply for extracting matrices from dataframe or list

I am using trade data between countries and would like to create a country by country matrix per item traded.我正在使用国家之间的贸易数据,并希望为每个交易的项目创建一个国家/地区矩阵。 A question like this has been asked before here and I am using that persons example data, it hasn't been answered, my question is different as I would not necesarily need to do this for multiple years.之前在这里已经问过这样的问题,我正在使用那个人的示例数据,但没有得到回答,我的问题是不同的,因为我不需要多年这样做。 DATA数据

usage <- data.frame(RC=c("DE", "IT", "USA","BRA", "ARG"),
                    Value=c(3,2,4,77,9,2,6,7,5,4),
                    Item = rep(c("Almonds", "Apples"), each=5))
import<- data.frame(RC=c("DE", "IT", "USA"),
                        PC = c("BRA", "ARG"),
                        Item = c("Almonds", "Apples"),
                        Value = c(1,5,3,2,8,3))


So I need to end up with ~450 identical matrixes for different products but all in the same matrix with all the countries included(so countries not trading a product should be included with value zero in that products matrix).所以我最终需要为不同的产品得到大约 450 个相同的矩阵,但都在同一个矩阵中,包括所有国家(所以不交易产品的国家应该在该产品矩阵中包含零值)。 Ultimately I would also like to fill the diagonal of these matrixes with the usage data from countries.最后,我还想用各国的使用数据填充这些矩阵的对角线。 I dont know if this is far too complex but i hope its possible.我不知道这是否太复杂了,但我希望它可能。 My code unfortunately does not work.....不幸的是,我的代码不起作用......

Any help in the right direction would be much appreciated.任何在正确方向上的帮助将不胜感激。

Edit: Solved by @user2474226.编辑:由@user2474226 解决。 I filled the diagonals by adding the usage data as trade data before the matrixes are made.在制作矩阵之前,我通过添加使用数据作为贸易数据来填充对角线。

Final code最终代码

usage$PC <- usage$RC #Duplicating the country column of usage
import2 <- rbind(import, usage) # adding the usage data to the trade data

import_YI <- split(import2, list(import2$Item))

trade_matrices <-lapply(import_YI, function(d) {
  x <- with(d, tapply(Value, list(RC, PC), sum)); 
  x[is.na(x)] <- 0; 
  x <- as.matrix(x);
  un1 <- unique(sort(c(colnames(x), rownames(x))));
  m2 <- matrix(0, NROW(un1), NROW(un1), dimnames = list(un1, un1));
  m2[rownames(x), colnames(x)] <- x;
  m2
  }
)

Many thanks to @user2474226 I learned a whole lot more and the solutions were very helpful.非常感谢@user2474226,我学到了很多东西,解决方案非常有帮助。 First time asking here, so didn't expect such a quick solution!第一次来这里问,没想到这么快就解决了! Desired Output matrix per product每个产品的期望输出矩阵

You could do something like this:你可以这样做:

import_YI <- split(import, list(import$Item))
lapply(import_YI, function(d) {
                     x <- with(d, tapply(Value, list(RC, PC), sum)); 
                     x[is.na(x)] <- 0; 
                     x})
#output
$Almonds
    ARG BRA
DE    0   1
IT    0   8
USA   0   3

$Apples
    ARG BRA
DE    2   0
IT    5   0
USA   3   0

I'm converting each dataframe in the list from long form to wide form via the tapply .我正在通过tapply将列表中的每个数据框从长格式转换为宽格式。 Where there's no traded product between the pair of countries, I'll get an NA, which I then replace with 0 .如果这对国家之间没有贸易产品,我将获得 NA,然后将其替换为0

Update : To create square matrices incorporating all the countries in rows and columns (using :更新:要创建包含行和列中所有国家/地区的方阵(使用:

lapply(import_YI, function(d) {
    x <- with(d, tapply(Value, list(RC, PC), sum)); 
    x[is.na(x)] <- 0; 
    x <- as.matrix(x);
    un1 <- unique(sort(c(colnames(x), rownames(x))));
    m2 <- matrix(0, NROW(un1), NROW(un1), dimnames = list(un1, un1));
    m2[rownames(x), colnames(x)] <- x;
    m2}
    )
# output
$Almonds
    ARG BRA DE IT USA
ARG   0   0  0  0   0
BRA   0   0  0  0   0
DE    0   1  0  0   0
IT    0   8  0  0   0
USA   0   3  0  0   0

$Apples
    ARG BRA DE IT USA
ARG   0   0  0  0   0
BRA   0   0  0  0   0
DE    2   0  0  0   0
IT    5   0  0  0   0
USA   3   0  0  0   0

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM