2013-12-19 4 views
1

У меня есть два набора данных, который разделяет подобные аспекты, например, набор данныеобъединение кадра данных по столбцу и строкам

name year region 
Jane 1980 1 
Jane 1981 2 
Mike 1980 1 
Mike 1985 4 
Bob  1980 NA 
Bob  1981 1 

и набор данных B

year 1 2 3 4 5 
1980 12 44 76 108 140 
1981 55 77 99 121 143 
1982 56 76 96 116 136 
1983 56 43 30 17 4 

Я хочу, чтобы создать новый столбец в первый набор данных под названием «income», который включает номера во втором наборе данных в соответствии с годом и столбцами 1-5. Например, поскольку Боб в 1980 году был в регионе 5, соответствующий income был бы равен 140. Если нет совпадения, я хочу, чтобы income был NA.

До сих пор я пытался

which(A$year==B$year & A$region==rownames(B)[2:6]) 

, но я не думаю, что это работает.

Я также хочу добавить, что не существует совпадений для всех точек данных, для переменной области A имеются значения NA для переменной области A, а количество лет в наборе данных B не охватывает все годы в данных set A.

ответ

1

Вот альтернатива, поскольку Joran заставляет меня работать ....

Создать matrix ваших доходов.

b <- as.matrix(B[-1]) 
rownames(b) <- B[,1] 

Использование match, чтобы соответствовать «год» с первого data.frame с rownames этой новой матрицы. Мы можем создать матрицу с этим как наш первый столбец (индекс строки) и «область» из вашего исходного data.frame в качестве второго столбца (индекс столбца).

cbind(match(A$year, rownames(b)), A$region) 
#  [,1] [,2] 
# [1,] 1 1 
# [2,] 2 2 
# [3,] 1 1 
# [4,] 2 4 
# [5,] 1 5 
# [6,] 2 1 

Мы можем использовать, чтобы извлечь соответствующие данные из матрицы «Ъ», и добавить его в оригинальной data.frame.

A$income <- b[cbind(match(A$year, rownames(b)), A$region)] 
A 
# name year region income 
# 1 Jane 1980  1  12 
# 2 Jane 1981  2  77 
# 3 Mike 1980  1  12 
# 4 Mike 1981  4 121 
# 5 Bob 1980  5 140 
# 6 Bob 1981  1  55 

Это предполагает, что мы начинаем с:

A <- read.table(text = "name year region 
Jane 1980 1 
Jane 1981 2 
Mike 1980 1 
Mike 1981 4 
Bob  1980 5 
Bob  1981 1",header = TRUE,sep = "") 

B <- read.table(text = "year 1 2 3 4 5 
1980 12 44 76 108 140 
1981 55 77 99 121 143 
1982 56 76 96 116 136 
1983 56 43 30 17 4",header = TRUE,sep = "",check.names = FALSE) 
+0

Спасибо за этот код! У меня есть одна проблема, хотя, поскольку не все совпадения данных совпадают, число ячеек после цикла cbind (совпадение (A $ year, rownames (b)), область A $) есть во всем наборе данных, и когда я пытаюсь чтобы извлечь это из b, я получаю сообщение об ошибке «индекс за пределами границ». Был бы способ извлечь тот, который я нашел, но оставить остальных как НС? – song0089

+0

@ Rusuer9000, даже с вашим редактированием, как мой ответ, так и работа Джорана. Вы можете увидеть, можете ли вы воссоздать небольшой набор данных (воспроизводимым образом, как мы это делали в этих ответах), которые демонстрируют проблему/ошибку? Благодарю. – A5C1D2H2I1M1N2O1R2T1

+0

Я выяснил проблему - матрица после выполнения cbind была матрицей символов, которую я должен был превратить в числовое значение перед извлечением из b. Спасибо! – song0089

1

Вам просто нужно преобразовать свой второй набор данных из широкого формата в длинный. Это можно сделать довольно легко, используя reshape2 и plyr:

library(reshape2) 
library(plyr) 

b <- read.table(text = "year 1 2 3 4 5 
1980 12 44 76 108 140 
1981 55 77 99 121 143 
1982 56 76 96 116 136 
1983 56 43 30 17 4",header = TRUE,sep = "",check.names = FALSE) 

a <- read.table(text = "name year region 
Jane 1980 1 
Jane 1981 2 
Mike 1980 1 
Mike 1981 4 
Bob  1980 5 
Bob  1981 1",header = TRUE,sep = "") 

b <- melt(b,id.vars = "year") 
b <- rename(b,c("variable" = "region")) 

merge(a,b,all.x = TRUE) 

В зависимости от типа вы хотите присоединиться, вы можете использовать либо all.y = TRUE или all = TRUE в merge.

+0

Не могли бы вы подробнее рассказать о том, что такое расплав и что означает «переменная» = «регион»? Я попробовал команду расплавления, но ничего не изменил. – song0089

+0

@ Rusuer9000, 'melt' преобразует данные в« длинную »форму. '" variable "=" region "' просто переименовывает переменную «переменная», которая создается, когда вы плавите «data.frame» в «region». – A5C1D2H2I1M1N2O1R2T1

+0

Joran, вы можете сохранить загрузку пакета только для 'rename', используя аргумент' variable.name' в 'melt':' melt (b, id.vars = "year", variable.name = "region") '. – A5C1D2H2I1M1N2O1R2T1

1

С Joran и Ананда принимают все хорошие варианты, вот нелепые один:

a$income <- 
    mapply(function(ro,co) b[ro,co], match(a$year,b$year), as.character(a$region)) 

# name year region income 
#1 Jane 1980  1  12 
#2 Jane 1981  2  77 
#3 Mike 1980  1  12 
#4 Mike 1981  4 121 
#5 Bob 1980  5 140 
#6 Bob 1981  1  55 

(При этом используется данные из ответа Джорана.)

+0

Я думаю, что вы используете данные из моего ответа и ответ @ joran, но, тем не менее, +1 :-) – A5C1D2H2I1M1N2O1R2T1

+0

Моя точка зрения заключалась в том, что, когда ваш 'mapply' ссылается на' a/b', вы назначаете его некоторому объекту названный 'A' ... – A5C1D2H2I1M1N2O1R2T1

+0

О, красные шары ... вы должны быть более откровенными со мной - это был долгий год! ;-) – thelatemail

3

Это моя третья попытка предоставить sqldf решения проблем преобразования данных за последние пару недель. Еще нет любви. Мы посмотрим, что думают люди на этот раз ...

Используя данные из ответа Joran в:

require(sqldf) 

sqldf('select 
      a.name 
      ,a.year 
      ,a.region 
      ,case 
      when region = 1 then b.X1 
      when region = 2 then b.X2 
      when region = 3 then b.X3 
      when region = 4 then b.X4 
      when region = 5 then b.X5 
      end income 
     from a 
      join b 
      on a.year= b.year') 

Здесь я «плавление» данные с помощью стандартного оператора SQL случай.

sqldf требует, чтобы я префиксные столбцы области в b с помощью X, поскольку механизм базы данных, работающий под пакетом, заставляет нецелые имена полей.

+1

плохо распространяют любовь sqldf, хотя утверждение довольно многословное. Я бы стал ленивым и начал бросать 'paste' там –

+0

@Manetheran, я согласен его немного более многословным и со многими более« широкими »полями, мы определенно захотим сократить жесткую кодировку через' paste', и т. д. Я собираюсь попасть в полете, но могу немного изменить это. Тем не менее, что SQL не хватает в многословии, он, как правило, компенсирует прозрачность. – joemienko

Смежные вопросы