Отображение кадра данных (с NA) в матрицу смежности n by n (как объект data.frame) - PullRequest
0 голосов
/ 07 ноября 2018

У меня есть объект из трех столбцов dataframe, записывающий данные о двусторонней торговле между 161 странами, данные имеют двоичный формат, содержащий 19687 строк, три столбца (репортер (rid), партнер (pid) и их двусторонний торговый поток (TradeValue) в данный год). rid или pid принимает значение от 1 до 161, и стране присваиваются те же rid и pid. Для любой данной пары (rid, pid), в которой rid = / = pid, TradeValue (rid, pid) = TradeValue (pid, rid ).

Данные (в R) выглядят так:

#load the data from dropbox folder
library(foreign)
example_data <- read.csv("https://www.dropbox.com/s/hf0ga22tdjlvdvr/example_data.csv?dl=1")

head(example_data, n = 10)
   rid pid TradeValue
1    2   3        500
2    2   7       2328
3    2   8    2233465
4    2   9      81470
5    2  12     572893
6    2  17     488374
7    2  19    3314932
8    2  23      20323
9    2  25         10
10   2  29    9026220

Данные были получены из базы данных UN Comtrade , каждый rid соединен с кратным pid для получения данных о двусторонней торговле, но, как видно, не каждый pid имеет числовой значение id, потому что я назначил rid или pid стране только в том случае, если имеется список соответствующих экономических показателей этой страны, поэтому в данных есть NA, несмотря на то, что между этой страной существует TradeValue страна, представившая отчет (rid). То же самое применяется, когда страна становится «репортером», в этой ситуации эта страна не сообщила о каких-либо TradeValue партнерам, и ее идентификационный номер отсутствует в столбце rid. (Следовательно, вы можете видеть, что столбец rid начинается с 2, потому что страна 1 (то есть, Афганистан) не сообщала никаких данных о двусторонней торговле с партнерами). Быстрая проверка со сводной статистикой помогает подтвердить это

length(unique(example_data$rid))
[1] 139
# only 139 countries reported bilateral trade statistics with partners
length(unique(example_data$pid))
[1] 162
# that extra pid is NA (161 + NA = 162)

Поскольку большинство стран сообщают данные о двусторонней торговле с партнерами, а для тех, кто этого не делает, они, как правило, являются малыми странами. Поэтому я хочу сохранить полный список из 161 страны и преобразовать этот example_data фрейм данных в матрицу смежности 161 x 161, в которой

  1. для тех стран, которые отсутствуют в столбце rid (например, rid == 1), создайте для каждой из них строку и задайте для всей строки (в матрице 161 x 161) значение 0.
  2. для тех стран (pid), которые не разделяют записи TradeValue с определенным rid, установите для этих ячеек значение 0.

Например, предположим, что в матрице смежности 5 x 5 страна 1 не сообщала о каких-либо статистических данных о торговле с партнерами, остальные четыре страны сообщали свои статистические данные о двусторонней торговле с другими (кроме страны 1). Исходный кадр данных похож на

rid	pid	TradeValue
2	3	223
2	4	13
2	5	9
3	2	223
3	4	57
3	5	28
4	2	13
4	3	57
4	5	82
5	2	9
5	3	28
5	4	82

, из которого я хочу преобразовать его в матрицу смежности 5 x 5 (в формате data.frame), требуемый вывод должен выглядеть следующим образом

	V1	V2	V3	V4	V5
1	0	0	0	0	0
2	0	0	223	13	9
3	0	223	0	57	28
4	0	13	57	0	82
5	0	9	28	82	0

И используя тот же метод на example_data, чтобы создать матрицу смежности 161 x 161. Однако, после пары проб и ошибок с reshape и другими методами, я все еще не мог обойтись с таким преобразованием, даже после первого шага.

Будет ли очень признательно, если кто-нибудь сможет просветить меня об этом?

1 Ответ

0 голосов
/ 07 ноября 2018

Я не могу прочитать файл dropbox, но попытался отработать ваш пример с 5-страничным фреймом данных -

country_num = 5

# check countries missing in rid and pid
rid_miss = setdiff(1:country_num, example_data$rid)
pid_miss = ifelse(length(setdiff(1:country_num, example_data$pid) == 0), 
                                     1, setdiff(1:country_num, example_data$pid))

# create dummy dataframe with missing rid and pid
add_data = as.data.frame(do.call(cbind, list(rid_miss, pid_miss, NA)))
colnames(add_data) = colnames(example_data)

# add dummy dataframe to original
example_data = rbind(example_data, add_data)

# the dcast now takes missing rid and pid into account
mat = dcast(example_data, rid ~ pid, value.var = "TradeValue")

# can remove first column without setting colnames but this is more failproof
rownames(mat) = mat[, 1]
mat = as.matrix(mat[, -1])

# fill in upper triangular matrix with missing values of lower triangular matrix 
# and vice-versa since TradeValue(rid, pid) = TradeValue(pid, rid)
mat[is.na(mat)] = t(mat)[is.na(mat)]

# change NAs to 0 according to preference - would keep as NA to differentiate 
# from actual zeros
mat[is.na(mat)] = 0

Помогает ли это?

...