Какой код в тесте Шапиро Вилка в R [дубликат]

Поскольку этот вопрос все еще активен, вот еще один подход:

  • ES6 / 2015
  • Неизменяемый (не изменяет исходные объекты)
  • Ручки массивы (объединяет их)

/**
* Performs a deep merge of objects and returns new object. Does not modify
* objects (immutable) and merges arrays via concatenation.
*
* @param {...object} objects - Objects to merge
* @returns {object} New object with merged key/values
*/
function mergeDeep(...objects) {
  const isObject = obj => obj && typeof obj === 'object';
  
  return objects.reduce((prev, obj) => {
    Object.keys(obj).forEach(key => {
      const pVal = prev[key];
      const oVal = obj[key];
      
      if (Array.isArray(pVal) && Array.isArray(oVal)) {
        prev[key] = pVal.concat(...oVal);
      }
      else if (isObject(pVal) && isObject(oVal)) {
        prev[key] = mergeDeep(pVal, oVal);
      }
      else {
        prev[key] = oVal;
      }
    });
    
    return prev;
  }, {});
}

// Test objects
const obj1 = {
  a: 1,
  b: 1, 
  c: { x: 1, y: 1 },
  d: [ 1, 1 ]
}
const obj2 = {
  b: 2, 
  c: { y: 2, z: 2 },
  d: [ 2, 2 ],
  e: 2
}
const obj3 = mergeDeep(obj1, obj2);

// Out
console.log(obj3);

430
задан epo3 5 October 2016 в 15:22
поделиться

9 ответов

UseMethod("t") сообщает вам, что t() является общей функцией ( S3 ), которая имеет методы для разных классов объектов.

Система отправки S3-метода

Для классов S3 вы можете использовать функцию methods для перечисления методов для определенной общей функции или класса.

> methods(t)
[1] t.data.frame t.default    t.ts*       

   Non-visible functions are asterisked
> methods(class="ts")
 [1] aggregate.ts     as.data.frame.ts cbind.ts*        cycle.ts*       
 [5] diffinv.ts*      diff.ts          kernapply.ts*    lines.ts        
 [9] monthplot.ts*    na.omit.ts*      Ops.ts*          plot.ts         
[13] print.ts         time.ts*         [<-.ts*          [.ts*           
[17] t.ts*            window<-.ts*     window.ts*      

   Non-visible functions are asterisked

«Невидимые функции являются звездочками» означает, что функция не экспортируется из пространства имен пакета. Вы можете просмотреть исходный код с помощью функции ::: (т. Е. stats:::t.ts) или с помощью getAnywhere(). getAnywhere() полезен, потому что вам не нужно знать, из какого пакета появилась функция.

> getAnywhere(t.ts)
A single object matching ‘t.ts’ was found
It was found in the following places
  registered S3 method for t from namespace stats
  namespace:stats
with value

function (x) 
{
    cl <- oldClass(x)
    other <- !(cl %in% c("ts", "mts"))
    class(x) <- if (any(other)) 
        cl[other]
    attr(x, "tsp") <- NULL
    t(x)
}
<bytecode: 0x294e410>
<environment: namespace:stats>

Система отправки S4

Система S4 - это более новый метод отправки и является альтернативой системе S3. Вот пример функции S4:

> library(Matrix)
Loading required package: lattice
> chol2inv
standardGeneric for "chol2inv" defined from package "base"

function (x, ...) 
standardGeneric("chol2inv")
<bytecode: 0x000000000eafd790>
<environment: 0x000000000eb06f10>
Methods may be defined for arguments: x
Use  showMethods("chol2inv")  for currently available ones.

Вывод уже содержит много информации. standardGeneric является индикатором функции S4. Предлагается метод для просмотра определенных методов S4:

> showMethods(chol2inv)
Function: chol2inv (package base)
x="ANY"
x="CHMfactor"
x="denseMatrix"
x="diagonalMatrix"
x="dtrMatrix"
x="sparseMatrix"

getMethod может использоваться для просмотра исходного кода одного из методов:

> getMethod("chol2inv", "diagonalMatrix")
Method Definition:

function (x, ...) 
{
    chk.s(...)
    tcrossprod(solve(x))
}
<bytecode: 0x000000000ea2cc70>
<environment: namespace:Matrix>

Signatures:
        x               
target  "diagonalMatrix"
defined "diagonalMatrix"

также методы с более сложными сигнатурами для каждого метода, например

require(raster)
showMethods(extract)
Function: extract (package raster)
x="Raster", y="data.frame"
x="Raster", y="Extent"
x="Raster", y="matrix"
x="Raster", y="SpatialLines"
x="Raster", y="SpatialPoints"
x="Raster", y="SpatialPolygons"
x="Raster", y="vector"

Чтобы увидеть исходный код для одного из этих методов, должна быть поставлена ​​целая сигнатура, например

getMethod("extract" , signature = c( x = "Raster" , y = "SpatialPolygons") )

Недостаточно предоставить частичную подпись

getMethod("extract",signature="SpatialPolygons")
#Error in getMethod("extract", signature = "SpatialPolygons") : 
#  No method found for function "extract" and signature SpatialPolygons

Функции, вызывающие невыгруженные функции

В случае ts.union, .cbindts и .makeNamesTs являются невыполненными функциями из пространство имен stats. Вы можете просмотреть исходный код невыгруженных функций с помощью оператора ::: или getAnywhere.

> stats:::.makeNamesTs
function (...) 
{
    l <- as.list(substitute(list(...)))[-1L]
    nm <- names(l)
    fixup <- if (is.null(nm)) 
        seq_along(l)
    else nm == ""
    dep <- sapply(l[fixup], function(x) deparse(x)[1L])
    if (is.null(nm)) 
        return(dep)
    if (any(fixup)) 
        nm[fixup] <- dep
    nm
}
<bytecode: 0x38140d0>
<environment: namespace:stats>

Функции, вызывающие скомпилированный код

Обратите внимание, что «скомпилированный» не обратитесь к байт-компилированному R-коду, созданному пакетом компилятора. Строка <bytecode: 0x294e410> в приведенном выше выводе указывает, что функция скомпилирована в байтах, и вы все еще можете просмотреть источник из командной строки R.

Функции, вызывающие .C, .Call, .Fortran, .External, .Internal или .Primitive вызывают точки входа в скомпилированном коде, поэтому вам нужно будет искать источники скомпилированного кода, если вы хотите полностью понять эту функцию. Это зеркало GitHub исходного кода R - достойное место для запуска. Функция pryr::show_c_source может быть полезным инструментом, так как она приведет вас непосредственно на страницу GitHub для вызовов .Internal и .Primitive. Пакеты могут использовать .C, .Call, .Fortran и .External; но не .Internal или .Primitive, поскольку они используются для вызова функций, встроенных в интерпретатор R.

Вызовы некоторых из вышеперечисленных функций могут использовать объект вместо символьной строки для ссылки на скомпилированные функция. В этих случаях объект имеет класс "NativeSymbolInfo", "RegisteredNativeSymbol" или "NativeSymbol"; и печать объекта дает полезную информацию. Например, optim вызывает .External2(C_optimhess, res$par, fn1, gr1, con) (обратите внимание, что это C_optimhess, а не "C_optimhess"). optim находится в пакете статистики, поэтому вы можете ввести stats:::C_optimhess, чтобы просмотреть информацию о вызываемой скомпилированной функции.

Скомпилированный код в пакете

Если вы хотите просмотреть скомпилированный код в пакете, вам нужно будет загрузить / распаковать исходный код пакета. Установленных двоичных файлов недостаточно. Исходный код пакета доступен из одного и того же CRAN (или совместимого с CRAN) репозитория, из которого первоначально был установлен пакет. Функция download.packages() может получить источник пакета для вас.

download.packages(pkgs = "Matrix", 
                  destdir = ".",
                  type = "source")

Это загрузит исходную версию пакета Matrix и сохранит соответствующий файл .tar.gz в текущем каталоге. Исходный код для скомпилированных функций можно найти в каталоге src несжатого и нераспределенного файла. Разомкнутый и необратимый шаг можно выполнить за пределами R или из R с помощью функции untar(). Можно объединить шаг загрузки и расширения в один вызов (обратите внимание, что один и тот же пакет может быть загружен и распакован таким образом):

untar(download.packages(pkgs = "Matrix",
                        destdir = ".",
                        type = "source")[,2])

В качестве альтернативы, если разработка пакета (например, через GitHub , R-Forge или RForge.net ), вы можете, вероятно, просмотреть исходный код онлайн.

Скомпилированный код в базовом пакете

Некоторые пакеты считаются «базовыми» пакетами. Эти пакеты поставляются с R, и их версия блокируется версией R. Примеры включают base, compiler, stats и utils. Таким образом, они недоступны в виде отдельных загружаемых пакетов на CRAN, как описано выше. Скорее, они являются частью дерева источников R в отдельных каталогах пакетов в /src/library/. Как получить доступ к источнику R, описан в следующем разделе.

Скомпилированный код, встроенный в интерпретатор R

Если вы хотите просмотреть встроенный код в интерпретаторе R, вы необходимо будет загрузить / распаковать источники R; или вы можете просмотреть источники в Интернете через репозиторий R Subversion или github mirror Winston Chang

.

Новая статья R Uwe Ligges [PDF] (стр. 43) является хорошей общей ссылкой о том, как просматривать исходный код для функций .Internal и .Primitive. Основные шаги - сначала искать имя функции в src/main/names.c, а затем искать имя «C-entry» в файлах в src/main/*.

397
ответ дан 19 revs, 8 users 54% 20 August 2018 в 09:34
поделиться
  • 1
    Если вы используете RStudio, он попытается вытащить источник для функции вашего текстового курсора, если вы нажмете клавишу F2. – Ari B. Friedman 26 October 2013 в 20:37
  • 2
    @Ari B. Friedman Извините за этот поздний вопрос. Будет ли RStudio также извлекать исходный код C для функции или только для функций, записанных в R? благодаря – Sam 24 February 2014 в 17:12
  • 3
    @Samir Я считаю, что это просто источник R. – Ari B. Friedman 25 February 2014 в 02:55
  • 4
    @ AriB.Friedman - спасибо Ари, это удобно. В моем случае мне все еще нужны знания, показанные в ответе (scale, который есть S3 - я получил UseMethod("scale"), а затем использовал getAnywhere(scale.default)). Но простые функции работают нормально. – Tomasz Gandor 12 May 2017 в 08:36
  • 5
    Имитация - это самая искренняя форма лести. Я предполагаю, что этот ответ / wiki пришел первым :) До этого rfaqs.com/source-code-of-r-method – JimLohse 27 March 2018 в 14:42

В R edit

new_optim <- edit(optim)

есть очень удобная функция. Он откроет исходный код optim, используя редактор, указанный в R options, а затем вы можете его редактировать и назначьте измененную функцию new_optim. Мне очень нравится эта функция, чтобы просматривать код или отлаживать код, например, печатать некоторые сообщения или переменные или даже назначать их глобальным переменным для дальнейшего исследования (конечно, вы можете использовать debug).

Если вы просто хотите просмотреть исходный код и не хотите, чтобы на вашей консоли был напечатан раздражающий длинный исходный код, вы можете использовать

invisible(edit(optim))

. Ясно, что это невозможно использовать для просмотра C / C ++ или Исходный код Fortran.

BTW, edit может открывать другие объекты, такие как список, матрица и т. Д., Который также показывает структуру данных с атрибутами. Функция de может быть использована для открытия редактора Excel (если он поддерживает GUI) для изменения рамки матрицы или данных и возврата нового. Иногда это удобно, но его следует избегать в обычном случае, особенно когда вы крупнее.

6
ответ дан Eric 20 August 2018 в 09:34
поделиться
  • 1
    Этот подход вызывает только тот же источник функции, который печатает функцию (то есть, как и в вопросе). Дальше / глубже, чем этот вопрос. – Brian Diggs 5 December 2014 в 07:17
  • 2
    @BrianDiggs Да, вы правы. Я не хотел дать ответ на этот вопрос, поскольку Джошуа дал вполне полный ответ. Я просто пытаюсь добавить что-то, связанное с темой, интересно и может быть полезно знать. – Eric 5 December 2014 в 17:23

View([function_name]) - например. View(mean) Обязательно используйте верхний регистр [V]. В редакторе откроется код только для чтения.

1
ответ дан Koo 20 August 2018 в 09:34
поделиться
  • 1
    Пожалуйста, избегайте коротких, недокументированных ответов. Пожалуйста, НЕ задавайте вопросы digg много лет, особенно те, которые прокомментированы со ссылками на уже принятые ответы. Удачи. – Ruslan Abuzant 11 January 2017 в 04:20
  • 2
    Этот только работает в Rstudio. – Axeman 11 January 2017 в 22:27

Пока функция написана в чистом R не C / C ++ / Fortran, можно использовать следующее. В противном случае лучшим способом является отладка и использование «прыгать в»:

> functionBody(functionName)
3
ответ дан MCH 20 August 2018 в 09:34
поделиться

Для непримитивных функций база R включает в себя функцию, называемую body(), которая возвращает тело функции. Например, источник функции print.Date() можно просмотреть:

body(print.Date)

выдает следующее:

{
    if (is.null(max)) 
        max <- getOption("max.print", 9999L)
    if (max < length(x)) {
        print(format(x[seq_len(max)]), max = max, ...)
        cat(" [ reached getOption(\"max.print\") -- omitted", 
            length(x) - max, "entries ]\n")
    }
    else print(format(x), max = max, ...)
    invisible(x)
}

Если вы работаете в скрипте и хотите, чтобы код функции как символ символа, вы можете получить его.

capture.output(print(body(print.Date)))

доставит вам:

[1] "{"                                                                   
[2] "    if (is.null(max)) "                                              
[3] "        max <- getOption(\"max.print\", 9999L)"                      
[4] "    if (max < length(x)) {"                                          
[5] "        print(format(x[seq_len(max)]), max = max, ...)"              
[6] "        cat(\" [ reached getOption(\\\"max.print\\\") -- omitted\", "
[7] "            length(x) - max, \"entries ]\\n\")"                      
[8] "    }"                                                               
[9] "    else print(format(x), max = max, ...)"                           
[10] "    invisible(x)"                                                    
[11] "}"     

Зачем мне это делать? Я создал пользовательский объект S3 (x, где class(x) = "foo") на основе списка. Один из участников списка (называемый «fun») был функцией, и я хотел print.foo() отобразить исходный код функции с отступом. Таким образом, я получил следующий фрагмент в print.foo():

sourceVector = capture.output(print(body(x[["fun"]])))
cat(paste0("      ", sourceVector, "\n"))

, который отступы и отображает код, связанный с x[["fun"]].

13
ответ дан MichaelChirico 20 August 2018 в 09:34
поделиться
  • 1
    ответ smci рекомендуется getAnywhere. Или вы можете просто использовать обратные выходы, если вы уже знаете имя оператора: `%in%`. – Joshua Ulrich 1 December 2015 в 21:32
  • 2
    @JoshuaUlrich не знал, что вы могли бы использовать backticks! Благодарю. getAnywhere также упоминается в вашем ответе, но я думаю, что конкретная ссылка на инфикс полезна для будущей ссылки на этот ответ. Я читал эту страницу много раз и все еще был немного озадачен, пытаясь найти код для таких функции на некоторое время - и я не думал, что он вписывается в поток любого другого ответа (который оба используют getAnywhere для другой цели). – MichaelChirico 1 December 2015 в 21:37

Он обнаруживается при отладке с помощью функции debug (). Предположим, вы хотите увидеть базовый код в функции транспонирования t (). Просто набрав «t», не обнаруживается много.

>t 
function (x) 
UseMethod("t")
<bytecode: 0x000000003085c010>
<environment: namespace:base>

Но, используя «debug (functionName)», он показывает базовый код, без внутренних элементов.

> debug(t)
> t(co2)
debugging in: t(co2)
debug: UseMethod("t")
Browse[2]> 
debugging in: t.ts(co2)
debug: {
    cl <- oldClass(x)
    other <- !(cl %in% c("ts", "mts"))
    class(x) <- if (any(other)) 
        cl[other]
    attr(x, "tsp") <- NULL
    t(x)
}
Browse[3]> 
debug: cl <- oldClass(x)
Browse[3]> 
debug: other <- !(cl %in% c("ts", "mts"))
Browse[3]> 
debug: class(x) <- if (any(other)) cl[other]
Browse[3]>  
debug: attr(x, "tsp") <- NULL
Browse[3]> 
debug: t(x)

EDIT: debugonce () выполняет то же самое без использования undebug ()

20
ответ дан Selva 20 August 2018 в 09:34
поделиться
  • 1
    Недостатки этого метода по сравнению с теми, которые приведены в принятом ответе, заключаются в том, что вам нужен вызов рабочей функции (все необходимые параметры указаны, приемлемо); и что в дополнение к исходному блоку кода вы также получаете каждый блок во время его запуска. Это отлично подходит для отладки, но не оптимально для получения источника. – Brian Diggs 12 August 2014 в 16:33
  • 2
    Да, это не оптимально. Но если вы умны, вы можете получить источник быстро и грязно, esp для встроенных функций. – Selva 13 August 2014 в 17:21
  • 3
    Я бы также рекомендовал использовать debugonce вместо debug в этом случае. – Joshua Ulrich 18 August 2014 в 21:20

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

Чтобы просмотреть / отредактировать его во всплывающем окне:

edit(getAnywhere('rfcv'), file='source_rfcv.r')

Для перенаправления на отдельный файл:

capture.output(getAnywhere('rfcv'), file='source_rfcv.r')
77
ответ дан smci 20 August 2018 в 09:34
поделиться
  • 1
    @ downvoters: это действительно ценно, и он попытался выяснить это. Существует множество причин, по которым вы можете отправить длинную функцию с большим количеством логики анализа аргументов в файл, а не на несколько экранов на консоли. Я не знал, как я сошел с моей задницы и понял это. Затем разместил его здесь. Позор вам для downvoting. – smci 12 September 2014 в 20:10
  • 2
    По общему признанию, getAnywhere является еще одним дурацким R-выбором имени для того, что должно было называться findOnSearchPath или аналогичным. – smci 21 August 2015 в 19:48

Вы также можете попытаться использовать print.function(), который является S3 generic, чтобы получить функцию записи в консоли.

2
ответ дан strboul 20 August 2018 в 09:34
поделиться
  • 1
    print.function() - метод S3 . Общий - print(). И вообще не рекомендуется напрямую обращаться к методам. Это побеждает всю цель общих функций и отправки методов. – Joshua Ulrich 27 December 2017 в 22:48
14
ответ дан MichaelChirico 31 October 2018 в 07:58
поделиться
Другие вопросы по тегам:

Похожие вопросы: