WedX - журнал о программировании и компьютерных науках

R plyr применяется в ряду

У меня есть такой фрейм данных:

    mat.in=data.frame(site=c('A','A','A','B','B','B'),
    var=c('product.A','product.B','energy','product.A','product.B','energy'),
    year.2011=c(12,10,40,14,12,60),year.2012=c(13,11,45,25,13,65))

Для каждого «сайта» я хочу разделить на «энергию» [в смысле numcol], чтобы получить:

    mat.out=data.frame(site=c('A','A','A','B','B','B'),
    var=c('product.A','product.B','energy','product.A','product.B','energy'),
    year.2011=c(12,10,40,14,12,60),year.2012=c(13,11,45,25,13,65),
    quot.2011=c(0.30,0.25,1.00,0.23,0.20,1.00),quot.2012=c(0.29,0.24,1.00,0.38,0.20,1.00))

Это идеально подходит для ddply из пакета plyr в сочетании с numcolwise из этого пакета. Но что-то у меня не получается - проблема выделить "энергетическую" составляющую.

Кто-нибудь знает, как это решить? [заранее спасибо...]

21.08.2012

Ответы:


1

Это сделает работу в вашем примере:

library(plyr)
ddply(mat.in, .(site), transform, quote.2011 = year.2011/year.2011[var=="energy"],      
      quote.2012 = year.2012/year.2012[var=="energy"])

Чтобы сделать это в более общем плане, я бы сначала melt данные превратил год в значение, а не имя столбца.

Вот как это будет работать с melt

library(reshape2)
mat.m <- melt(mat.in, id.vars=1:2, variable.name="year")
mat.m$year <- sub("year.", "", mat.m$year)
mat.out <- ddply(mat.m, .(site, year), transform, quote = value/value[var=="energy"])
21.08.2012
  • Спасибо Шон, это работает! Я пробовал это также с вашим предложением расплава, но получил «нечисловой аргумент для бинарного оператора». 21.08.2012

  • 2

    Классный ответ от @seancarmody.

    Вот еще один способ сделать это с помощью базовых функций:

    # Select and join frames
    mat.out<-merge(mat.in[grep("product", mat.in$var),], mat2 <- mat.in[mat.in$var=="energy",], "site")
    # Calculate the quot values
    mat.out$quot.2011=mat.out$year.2011.x/mat.out$year.2011.y
    mat.out$quot.2012=mat.out$year.2012.x/mat.out$year.2012.y
    
    # And if needs be you can remove the energy columns
    mat.out[,-c(5,6,7)]
    

    И вот способ сделать это с помощью sqldf:

    variable<-'p.site,p.var,p.year_2011,p.year_2012,
               p.year_2011/e.year_2011 AS quot_2011,
               p.year_2012/e.year_2012 AS quot_2012'
    tables<- '(SELECT *
               FROM    `mat.in`
               WHERE   var LIKE \"product%\"
               )
               AS p,
               (SELECT *
               FROM    `mat.in`
               WHERE   var LIKE \"energy\"
               )
               AS e'
    
    fn$sqldf("SELECT $variable FROM $tables WHERE  p.site=e.site")
    

    А вот способ использования data.table:

    dt <- data.table(mat.in, key="site")
    # Join
    mat.out <- dt[var %like% "product"][dt[var=="energy"]]
    # Calculate
    mat.out <- mat.out[,quot.2011:=year.2011/year.2011.1]
    mat.out <- mat.out[,quot.2012:=year.2012/year.2012.1]
    

    Редактировать от Мэтью:

    Опираясь на это, немного более продвинутый (и более быстрый) data.table способ с использованием объединить унаследованную область :

    dt <- data.table(mat.in, key="site")
    dt[dt[var=="energy"],quot.2011:=year.2011/i.year.2011]
    dt[dt[var=="energy"],quot.2012:=year.2012/i.year.2012]
    

    Обратите внимание на префикс i., который говорит, что эта переменная должна быть получена из i, а не из x. Аналогично префиксам имен таблиц SQL. Это позволяет избежать большого шага merge; методика, описанная в FAQ 1.12.

    Когда будет реализовано несколько := в j, это станет:

    dt <- data.table(mat.in, key="site")
    dt[dt[var=="energy"], { quot.2011:=year.2011/i.year.2011
                            quot.2012:=year.2012/i.year.2012 } ]
    
    21.08.2012
  • Спасибо Шон и РОЛО. Я не могу заставить работать версию Melt [Ошибка в var == energy : сравнение (1) возможно только для атомарных и списочных типов, но первый вариант работает. 21.08.2012
  • Вы используете reshape2? Какая версия Р? Я просто попробовал код еще раз и не получил никаких ошибок. 21.08.2012
  • Привет, Шон и РОЛО - моя вина; он работает с кодом на этой странице, но не с моим [намного большим] набором данных. Не могу найти что это. Я внимательно следил за шагами, проверял с помощью str(mydata) и т.д. 21.08.2012
  • Может неправильные значения в столбце var? Что говорят вам summary(mat.in$var) и class(mat.in$var) на большом столе? 21.08.2012
  • Привет, Роло, сводка (mat.in $ var дает: режим класса длины 211806 символьных символов. class mat.in $ var дает «символ». Я заметил, что количество значений за «год» не то же самое, например, 2008 = 264709 а 2009=264701,может быть причина в этом?Использование R 2.14 64 бит на #!Linux, reshape2. 23.08.2012
  • Это может быть проблемой, но, возможно, вы уже выяснили это за это время. Вы также можете взглянуть на параметр слияния all=TRUE, чтобы получить «полное соединение». 25.08.2012

  • 3

    Просто используя базовые функции:

    mat.r <- reshape(mat.in, direction="long", varying=3:4)
     # Could not figure out how to get the divisor "lined up" unless db-normalized
    matd <- as.data.frame(lapply( split(mat.r, list(mat.r[,1], mat.r[,3]) ), 
                                  FUN=function(x) x$year/x$year[x$var=="energy"]) )
    
    #----------------
    matd
      A.2011    B.2011    A.2012    B.2012
    1   0.30 0.2333333 0.2888889 0.3846154
    2   0.25 0.2000000 0.2444444 0.2000000
    3   1.00 1.0000000 1.0000000 1.0000000
    
     reshape(matd, direction="long", varying=list(1:2, 3:4))[2:3]
           A.2011    A.2012
    1.1 0.3000000 0.2888889
    2.1 0.2500000 0.2444444
    3.1 1.0000000 1.0000000
    1.2 0.2333333 0.3846154
    2.2 0.2000000 0.2000000
    3.2 1.0000000 1.0000000
    
     mat.out <- cbind(mat.in, reshape(matd, direction="long", varying=list(1:2, 3:4))[2:3])
     mat.out
     #------------------    
        site       var year.2011 year.2012    A.2011    A.2012
    1.1    A product.A        12        13 0.3000000 0.2888889
    2.1    A product.B        10        11 0.2500000 0.2444444
    3.1    A    energy        40        45 1.0000000 1.0000000
    1.2    B product.A        14        25 0.2333333 0.3846154
    2.2    B product.B        12        13 0.2000000 0.2000000
    3.2    B    energy        60        65 1.0000000 1.0000000
    
    21.08.2012
  • Спасибо ДВин. Единственное отсутствующее решение — пакет [fast] data.table. 21.08.2012
  • Добавлен data.table (хотя и не обязательно самый оптимальный способ его использования). 21.08.2012
  • Новые материалы

    Как проанализировать работу вашего классификатора?
    Не всегда просто знать, какие показатели использовать С развитием глубокого обучения все больше и больше людей учатся обучать свой первый классификатор. Но как только вы закончите..

    Работа с цепями Маркова, часть 4 (Машинное обучение)
    Нелинейные цепи Маркова с агрегатором и их приложения (arXiv) Автор : Бар Лайт Аннотация: Изучаются свойства подкласса случайных процессов, называемых дискретными нелинейными цепями Маркова..

    Crazy Laravel Livewire упростил мне создание электронной коммерции (панель администратора и API) [Часть 3]
    Как вы сегодня, ребята? В этой части мы создадим CRUD для данных о продукте. Думаю, в этой части я не буду слишком много делиться теорией, но чаще буду делиться своим кодом. Потому что..

    Использование машинного обучения и Python для классификации 1000 сезонов новичков MLB Hitter
    Чему может научиться машина, глядя на сезоны новичков 1000 игроков MLB? Это то, что исследует это приложение. В этом процессе мы будем использовать неконтролируемое обучение, чтобы..

    Учебные заметки: создание моего первого пакета Node.js
    Это мои обучающие заметки, когда я научился создавать свой самый первый пакет Node.js, распространяемый через npm. Оглавление Глоссарий I. Новый пакет 1.1 советы по инициализации..

    Забудьте о Matplotlib: улучшите визуализацию данных с помощью умопомрачительных функций Seaborn!
    Примечание. Эта запись в блоге предполагает базовое знакомство с Python и концепциями анализа данных. Привет, энтузиасты данных! Добро пожаловать в мой блог, где я расскажу о невероятных..

    ИИ в аэрокосмической отрасли
    Каждый полет – это шаг вперед к великой мечте. Чтобы это происходило в их собственном темпе, необходима команда астронавтов для погони за космосом и команда технического обслуживания..


    Для любых предложений по сайту: [email protected]