2015-09-23 3 views
4

Я отчаянно пытаюсь заполнить матрицу значениями из фрейма данных. Это торговые данные, так что кадр данных выглядит следующим образом:Как заполнить пустую матрицу значениями данных

country1 country2 value 
1 Afghanistan Albania 30 
2 Afghanistan Albania 81 
3 Afghanistan China  5 
4  Albania Germany  6 
5  China Germany  8 
6  China Turkey 900 
7  Germany Turkey 12 
8  Germany  USA  3 
9  Germany Zambia 700 

Использование уникального и сортировки команд я создал список из всех стран, которые происходят в ДФ (и превратили его в матрицу):

 countries_sorted 
[1,] "Afghanistan" 
[2,] "Albania"  
[3,] "China"   
[4,] "Germany"  
[5,] "Turkey"   
[6,] "USA"   
[7,] "Zambia"  

Используя этот «список», я создал пустые торговую матрицу (7x7):

   Afghanistan Albania China Germany Turkey USA Zambia 
Afghanistan   NA  NA NA  NA  NA NA  NA 
Albania    NA  NA NA  NA  NA NA  NA 
China    NA  NA NA  NA  NA NA  NA 
Germany    NA  NA NA  NA  NA NA  NA 
Turkey    NA  NA NA  NA  NA NA  NA 
USA     NA  NA NA  NA  NA NA  NA 
Zambia    NA  NA NA  NA  NA NA  NA 

Я безнадежно неисправный, чтобы заполнить эту матрицу с номерами/суммы от я e значение столбца df. я пытался что-то вроде этого:

a<-cast(df, country1~country2 , sum) 

, который работает до такой степени, НО матрица не сохраняет свой первоначальный формат 7x7, который является то, что мне нужно иметь матрицу, где диагональ все 0s.

> a 
    country1 Albania China Germany Turkey USA Zambia 
1 Afghanistan  111  5  0  0 0  0 
2  Albania  0  0  6  0 0  0 
3  China  0  0  8 900 0  0 
4  Germany  0  0  0  12 3 700 

Пожалуйста, любой, у кого есть решение ????

ответ

0

Поскольку это только верхняя диагональная матрица, а диагональ равна 0, то она остается неизменной, за исключением первого столбца, который удаляется, так как он не содержит информации (только нули). Вы можете просто добавить его в матрицу с помощью cbind:

Z = matrix(rep(0,7),ncol=1) 
newMatrix = cbind(Z,oldMatrix) 
4

Начиная с этими наборами 2 данных:

#your data.frame 
df <- read.table(header=T, file='clipboard', stringsAsFactors = F) 
#the list of unique countries 
countries <- unique(c(df$country1,df$country2)) 

Вы можете сделать:

#create all the country combinations 
newdf <- expand.grid(countries, countries) 
#change names 
colnames(newdf) <- c('country1', 'country2') 
#add a value of 0 for the new combinations (won't affect outcome) 
newdf$value <- 0 
#row bind with original dataset 
df2 <- rbind(df, newdf) 


#and create the table using xtabs: 
#the aggregate function will create the sum of the value for each combination 
> xtabs(value ~ country1 + country2, aggregate(value~country1+country2,df2,sum)) 
      country2 
country1  Afghanistan Albania China Germany Turkey USA Zambia 
    Afghanistan   0  111  5  0  0 0  0 
    Albania    0  0  0  6  0 0  0 
    China     0  0  0  8 900 0  0 
    Germany    0  0  0  0  12 3 700 
    Turkey    0  0  0  0  0 0  0 
    USA     0  0  0  0  0 0  0 
    Zambia    0  0  0  0  0 0  0 
+0

Мне не понравилось, что мы использовали умный подход 'rbind' (с 0' value') вместо объединения кадров данных. Может быть быстрее, когда есть больше данных, верно? – AntoniosK

+1

@ AntoniosK Хммм «rbind» имеет плохую репутацию с точки зрения эффективности из-за семантики copy-on-modify (требуется больше памяти и делает ее медленнее). Функция 'left_join', которую вы используете с' dplyr', определенно более эффективна. Теперь, с точки зрения скорости, в этом случае я перебираю только два data.frames, поэтому я не уверен, какой из них будет быстрее (вероятно, 'left_join'), но' dplyr' будет более эффективным, когда есть ограничения с RAM , Kai kali mas mera Antwni :) – LyzandeR

+1

Отлично. Полезно знать @LyzandeR. (Twra me koufanes! Kali mas mera file ...) – AntoniosK

1

И альтернативным решением, чтобы @ Отличный ответ LyzandeR, используя пакеты dplyr и tidyr.

dt = read.table(text= 
"country1 country2 value 
Afghanistan Albania 30 
Afghanistan Albania 81 
Afghanistan China  5 
Albania Germany  6 
China Germany  8 
China Turkey 900 
Germany Turkey 12 
Germany  USA  3 
Germany Zambia 700", header=T, stringsAsFactors=F) 

library(dplyr) 
library(tidyr) 

dt2 = 
    dt %>% 
     group_by(country1,country2) %>% # for every combination of countries 
     summarise(SumValue = sum(value)) # get the sum of value 

# get all possible countries that appear in your dataset 
list_countries = union(dt2$country1, dt2$country2) 

expand.grid(country1=list_countries, country2=list_countries, stringsAsFactors = F) %>% # create all possible combinations of countries 
    left_join(dt2, by=c("country1","country2")) %>% # join back info whenever it is found 
    mutate(SumValue = ifelse(is.na(SumValue),0,SumValue)) %>% # replace NAs with 0s 
    spread(country2,SumValue) # reshape data 

#  country1 Afghanistan Albania China Germany Turkey USA Zambia 
# 1 Afghanistan   0  111  5  0  0 0  0 
# 2  Albania   0  0  0  6  0 0  0 
# 3  China   0  0  0  8 900 0  0 
# 4  Germany   0  0  0  0  12 3 700 
# 5  Turkey   0  0  0  0  0 0  0 
# 6   USA   0  0  0  0  0 0  0 
# 7  Zambia   0  0  0  0  0 0  0 
Смежные вопросы