Использование if-квалификатора с egen в Stata - PullRequest
9 голосов
/ 06 марта 2012

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

Market    Firm   Price
----------------------
1         1      100
1         2      150
1         3      125
2         1      50
2         2      100
2         3      75
3         1      100
3         2      200
3         3      200

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

Market    Firm   Price    AvRivalPrice
------------------------------------
1         1      100      137.2
1         2      150      112.5
1         3      125      125
2         1      50       87.5
2         2      100      62.5
2         3      75       75
3         1      100      200
3         2      200      150
3         3      200      150

Чтобы получить среднее значение по группе, я мог бы использовать команду egen:

egen AvPrice = mean(price), by(Market)

Но это не исключало бы собственную цену фирмы в среднеми, насколько мне известно, использование квалификатора if только изменит наблюдения, над которыми он работал, а не группы, по которым он усредняется.Есть ли простой способ сделать это, или мне нужно создавать циклы и генерировать каждое среднее вручную?

Ответы [ 3 ]

9 голосов
/ 20 февраля 2013

Это старая тема, которая до сих пор интересна, поэтому материалы и методы, пропущенные в первый раз, все еще применяются

Более общий метод заключается в работе с итогами.В самом простом случае, общее количество других = общее количество всего - это значение.В фреймворке egen, который будет выглядеть как

egen total = total(price), by(market) 
egen n = total(!missing(price)), by(market) 
gen avprice = (total - cond(missing(price), 0, price)) / cond(missing(price), n, n - 1) 

Функция total() egen игнорирует пропущенные значения в своем аргументе.Если пропущенные значения отсутствуют, мы не хотим включать их в счетчик, но мы можем использовать !missing(), что дает 1, если не пропущено, и 0, если пропущено.egen s count() - это еще один способ сделать это.

Код, приведенный ранее, дает неправильный ответ, если пропуски присутствуют, поскольку они включены в счет _N.

Даже если значение отсутствует, среднее значение других значений все еще имеет смысл.

Если никакое значение не пропущено, последняя строка выше упрощается до

gen avprice = (total - price) / (n - 1) 

До сих пор это, возможно, выглядит не более, чем маленький вариант предыдущего кода, но оно легко расширяется дос использованием весов.Предположительно, мы хотим получить средневзвешенное значение цен других людей, равное weight.Мы можем использовать тот факт, что total() работает с выражениями, которые могут быть более сложными, чем просто имена переменных.Действительно, приведенный выше код уже сделал это, но его часто упускают из виду.

egen wttotal = total(weight * price), by(market) 
egen sumwt = total(weight), by(market) 
gen avprice = (wttotal - price * weight) / (sumwt - weight) 

Как и раньше, если price или weight отсутствует, вам нужен более сложный код, или просто чтобы исключить такие наблюдения из расчетов.

См.также FAQ по Stata

Как создать переменные, суммирующие для каждого отдельного свойства других членов группы?

http://www.stata.com/support/faqs/data-management/creating-variables-recording-properties/

для более широкойранговое обсуждение.

(Если числа становятся большими, работайте с double s.)

РЕДАКТИРОВАТЬ 2 марта 2018 г. Это был более новый пост в старой ветке, который, в свою очередь, нуждается в обновлении.rangestat (SSC) может использоваться здесь и дает однострочные решения.Не удивительно, что опция excludeself была явно добавлена ​​для такого рода проблем.Но в то время как решение для средств легко с использованием тождества

среднее для других = (общая - ценность для себя) / (количество - 1)

, многие другие сводные показатели не поддаютсяПодобный, простой трюк и в этом смысле rangestat включает в себя гораздо более общее кодирование.

clear
input Market    Firm   Price
1         1      100
1         2      150
1         3      125
2         1      50
2         2      100
2         3      75
3         1      100
3         2      200
3         3      200
end 

rangestat (mean) Price, interval(Firm . .) by(Market) excludeself 

list, sepby(Market) 

     +----------------------------------+
     | Market   Firm   Price   Price_~n |
     |----------------------------------|
  1. |      1      1     100      137.5 |
  2. |      1      2     150      112.5 |
  3. |      1      3     125        125 |
     |----------------------------------|
  4. |      2      1      50       87.5 |
  5. |      2      2     100       62.5 |
  6. |      2      3      75         75 |
     |----------------------------------|
  7. |      3      1     100        200 |
  8. |      3      2     200        150 |
  9. |      3      3     200        150 |
     +----------------------------------+
7 голосов
/ 06 марта 2012

Это способ избежать явных циклов, хотя он занимает несколько строк кода:

by Market: egen Total = total(Price)
replace Total = Total - Price
by Market: gen AvRivalPrice = Total / (_N-1)
drop Total
5 голосов
/ 07 марта 2012

Вот более короткое решение с меньшим количеством строк, которое как бы объединяет вашу оригинальную мысль и решение @ onestop:

      egen AvPrice = mean(price), by(Market)
      bysort Market: replace AvPrice = (AvPrice*_N - price)/(_N-1)

Это все хорошо для переписи фирм.Если у вас есть образец фирм, и вам нужно применить весовые коэффициенты, я не уверен, что будет хорошим решением.Мы можем провести мозговой штурм, если необходимо.

...