Arhn - архитектура программирования

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

Я хочу, чтобы элементы, указанные в моем фрейме данных, были заменены аргументом, который я ввел в функцию, однако на данный момент он просто заменяет элементы аргументом, который я использовал для первоначального определения функции (мне трудно объяснить - надеюсь, мой код и картинки немного прояснят это!)

Project_assign <- function(prjct) {
  Truth_vector <- is.element((giraffe[,1]),(prjct[,1]))
  giraffe[which(Truth_vector),5] <- 'prjct'
  assign('giraffe' , giraffe , envir= .GlobalEnv)
}
Project_assign(spine_hlfs)

В основном это работает, однако элементы заменяются на prjct вместо spin_hlfs https://i.stack.imgur.com/uuPnv.png

Если я смогу заставить это работать как задумано, то затем я создам вектор со всеми именами проекта и использую lapply с этой функцией, что избавит меня от большого количества ручной работы каждые несколько месяцев. Я относительно новичок в R, поэтому любые объяснения приветствуются.

06.12.2017

  • Не могли бы вы включить некоторые примеры данных, чтобы сделать ваш код воспроизводимым, а также предоставить ожидаемый результат. Мы ничего не знаем о giraffe, prjct, spine_hlfs и т. д. Публикация изображений/скриншотов обычно мало чем помогает. Наконец, использование assign, как правило, не очень хорошая идея (подробнее см., например, здесь) . 06.12.2017
  • Я приведу пример (не могу использовать его, так как данные извлекаются из базы данных sql) - однако Giraffe - это фрейм данных с ключами runkeys от 1 до 500 ,pine_hlfs также является фреймом данных, но содержит только определенные runkeys, которые являются подмножеством жираф (например, 44, 260, 478). prjct — это аргумент функции, я хочу, чтобы столбец «проект» в фрейме данных жирафа обновлялся конкретным именем (в данном случае spin_hlfs) только там, где совпадают ключи запуска. 06.12.2017

Ответы:


1

Звучит как простая замена, основанная на matchзаписях между кадрами данных (списком) запроса и кадром данных субъекта.

Вот пример, основанный на некоторых смоделированных данных.

Сначала я моделирую данные для subject dataframe:

# Sample data
giraffe <- data.frame(
    runkeys = seq(1:500),
    col1 = runif(500),
    col2 = runif(500),
    col3 = runif(500),
    col4 = runif(500));

Затем я моделирую runkeys данных для 2 запросов dataframes:

spine_hlfs <- data.frame(
    runkeys = c(44, 260, 478));
ir_dia <- data.frame(
    runkeys = c(10, 20, 30))

запрос dataframes хранится в list:

lst.runkeys <- list(
    spine_hlfs = spine_hlfs,
    ir_dia = ir_dia);

Чтобы пометить runkeys записей, присутствующих в любом из запросов dataframes, мы можем использовать цикл for для match runkeys записей из каждого запроса dataframe:

# This is the critical line that loops through the dataframe
# and flags runkeys in giraffe with the name of the query dataframe
for (i in 1:length(lst.runkeys)) {
    giraffe[match(lst.runkeys[[i]]$runkeys, giraffe$runkeys), 5] <- names(lst.runkeys)[i];
}

Это результат subject dataframe после сопоставления runkeys записей. Я показываю только строки, в которых заменены записи в столбце 5.

giraffe[grep("(spine_hlfs|ir_dia)", giraffe[, 5]), ];
10       10 0.7401977 0.005703928 0.6778921     ir_dia
20       20 0.7954076 0.331462567 0.7637870     ir_dia
30       30 0.5772808 0.183716142 0.6984193     ir_dia
44       44 0.9701355 0.655736489 0.4917452 spine_hlfs
260     260 0.1893012 0.600140166 0.0390346 spine_hlfs
478     478 0.7655976 0.910946623 0.9779205 spine_hlfs
06.12.2017
  • Извините за задержку с ответом. Ваш код делает то, что мне нужно (за исключением того, что в строке #replace я бы назначил spin_hlfs вместо prjct), однако в моей ситуации «spine_hlfs» — это всего лишь один из многих фреймов данных, которые мне нужно сопоставить с «жирафом», что означает, что мне придется скопируйте этот код много раз, только меняя имя фрейма данных для каждого (т.е. не только «spine_hlfs», но и «spine_moe», «spine_dia», .... и т. д.). Я пытаюсь создать функцию, которая бы обобщала этот код, чтобы он охватывал все кадры данных сразу - я там 99%, за исключением того, что при использовании этого аргумента он назначает «prjct», а не «spine_hlfs». 06.12.2017
  • Для дальнейшего уточнения: я хочу, чтобы при вызове «Project_assign(spine_hlfs)» он обновлял столбец «проект» в giraffe с помощью «spine_hlfs» в каждой строке, где совпадают Runkeys. Затем, если я вызову «Project_assign(ir_dia)», он обновит столбец «project» в giraffe с помощью «ir_dia», где совпадают Runkeys и так далее. Каждый кадр данных подмножества имеет уникальные runkeys для других кадров данных подмножества. Как только я получу эту функцию, я попытаюсь создать список, содержащий все подмножества фреймов данных, а затем наложить список с помощью этой функции, теоретически делая код намного короче и экономя время. 06.12.2017
  • @Maharero Я все еще не вижу необходимости в функции. Просто сохраните все запросы dataframes в списке и переберите их, чтобы заменить записи, где у вас есть соответствующие runkeys. В attach определенно нет необходимости! Я обновил свой пример, чтобы показать вам работающий минимальный пример с двумя запросами dataframes. 06.12.2017
  • Я читаю о прикреплении и постараюсь избежать этого, если смогу (не нужно это для цикла for, как вы делаете, однако я думаю, что это необходимо для функции). Ваш метод очень похож на то, что мне нужно - единственное, что мне нужно, это чтобы в вашем примере внутри столбца 4 ключи 10, 20, 30 должны были говорить «ir_dia» вместо «prjct», а ключи 44, 260, 478 должны скажите «spine_hlfs» вместо «prjct». Вот почему я подумал, что функция необходима, так как строка внутри моей функции # giraffe[what(Truth_vector),5] ‹- 'prjct' # динамически заменяет 'prjct' на то, что я вызываю в аргументе функции. 06.12.2017
  • @Maharero Нет, в функции определенно нет необходимости, несмотря на вашу настойчивость. Здесь можно использовать цикл for. Возможно, вы читали о циклах for и о том, как их вообще избежать в R. В основном это правда, но не в целом (история более сложная и восходит к старому S-plus). Это отличный пример хорошего использования цикла for. Я обновил свой пример, заменив записи именем базы данных запросов. Это должно быть то, что вам нужно. attach — это зло, и его следует избегать. 06.12.2017
  • @Махареро PS. Есть еще одна причина, по которой использование функции в этом случае не имеет особого смысла: R создаст еще одну копию dataframe, которую вы передаете в качестве аргумента функции (это потому, что R не знает о передаче объектов по ссылке). Таким образом, вам понадобится (как минимум) в два раза больше памяти только для хранения/чтения одного dataframe. 06.12.2017
  • @MauritsEvers, я думаю, вы имеете в виду назначить. fortunes::fortune(236) говорит: Функция назначения должна использоваться только теми, кто полностью понимает, почему вам никогда не следует использовать функцию назначения. -- Грег Сноу R-help (июль 2009 г.) 06.12.2017
  • Спасибо как за ваши методы, так и за ваше терпение, циклы for гораздо более универсальны, чем я думал раньше, и теперь я также знаю о пакете/методе data.table (я не могу указать, что существует более 1 принятого отвечать?) 06.12.2017
  • @Maharero, вы можете принять только один ответ как наиболее удобный для вашего вопроса, но вы можете проголосовать за оба ответа (нажмите на треугольник вверх над галочкой) по своему усмотрению. 06.12.2017
  • @Uwe Да, моя ошибка, я имел в виду assign. Благодарю за разъяснение. Я уже разместил ссылку на сообщение SO, в котором обсуждались опасности assign выше. 06.12.2017
  • @Maharero Не беспокойтесь, рад помочь, и я рад, что в конце концов все получилось. 06.12.2017

  • 2

    Насколько я понял намерения ОП из множества комментариев, он хочет обновить фрейм данных giraffe с помощью имени многих других фреймов данных, где runkey соответствует.

    Этого можно добиться, объединив другие фреймы данных в один объект data.table, обрабатывая имена фреймов данных как данные и, наконец, обновив giraffe в соединении.

    Образец данных

    Согласно OP, giraffe состоит из 500 строк и 5 столбцов, включая runkey и project. project инициализируется здесь как столбец символов для последующего соединения с именами фреймов данных.

    set.seed(123L) # required for reproducible data
    giraffe <- data.frame(runkey = 1:500,
                          X2 = sample.int(99L, 500L, TRUE),
                          X3 = sample.int(99L, 500L, TRUE),
                          X4 = sample.int(99L, 500L, TRUE),
                          project = "",
                          stringsAsFactors = FALSE)
    

    Затем есть ряд фреймов данных, которые содержат только один столбец runkey. Согласно OP, runkey является дизъюнктным, т. Е. Объединенный набор всех runkey не содержит дубликатов.

    spine_hlfs <- data.frame(runkey = c(1L, 498L, 5L))
    ir_dia     <- data.frame(runkey = c(3L, 499L, 47L, 327L))
    

    Предложенное решение

    # specify names of data frames
    df_names <- c("spine_hlfs", "ir_dia")
    # create named list of data frames 
    df_list <- mget(df_names)
    # update on join 
    library(data.table)
    setDT(giraffe)[rbindlist(df_list, idcol = "df.name"), on = "runkey", project := df.name][]
    
         runkey X2 X3 X4    project
      1:      1  2 44 63 spine_hlfs
      2:      2 73 99 77           
      3:      3 43 20 18     ir_dia
      4:      4 73 12 40           
      5:      5  2 25 96 spine_hlfs
     ---                           
    496:    496 75 45 84           
    497:    497 24 63 43           
    498:    498 33 53 81 spine_hlfs
    499:    499  1 33 16     ir_dia
    500:    500 99 77 41
    

    Объяснение

    setDT() принуждает giraffe к data.table. rbindlist(df_list, idcol = "df.name") создает комбинированную data.table из списка фреймов данных, тем самым заполняя столбец df.name именами элементов списка:

          df.name runkey
    1: spine_hlfs      1
    2: spine_hlfs    498
    3: spine_hlfs      5
    4:     ir_dia      3
    5:     ir_dia    499
    6:     ir_dia     47
    7:     ir_dia    327
    

    Этот промежуточный результат объединяется runkey с giraffe. Столбец project обновляется содержимым df.name только для совпадающих строк.

    Альтернативное решение

    Это зацикливается на df_names и выполняет повторяющиеся соединения, которые обновляют giraffe на месте:

    setDT(giraffe)
    for (x in df_names) giraffe[get(x), on = "runkey", project := x]
    giraffe[]
    
    06.12.2017
  • Я также добавил решение цикла for. 06.12.2017
  • Новые материалы

    Коллекции публикаций по глубокому обучению
    Последние пару месяцев я создавал коллекции последних академических публикаций по различным подполям глубокого обучения в моем блоге https://amundtveit.com - эта публикация дает обзор 25..

    Представляем: Pepita
    Фреймворк JavaScript с открытым исходным кодом Я знаю, что недостатка в фреймворках JavaScript нет. Но я просто не мог остановиться. Я хотел написать что-то сам, со своими собственными..

    Советы по коду Laravel #2
    1-) Найти // You can specify the columns you need // in when you use the find method on a model User::find(‘id’, [‘email’,’name’]); // You can increment or decrement // a field in..

    Работа с временными рядами спутниковых изображений, часть 3 (аналитика данных)
    Анализ временных рядов спутниковых изображений для данных наблюдений за большой Землей (arXiv) Автор: Рольф Симоэс , Жильберто Камара , Жильберто Кейрос , Фелипе Соуза , Педро Р. Андраде ,..

    3 способа решить квадратное уравнение (3-й мой любимый) -
    1. Методом факторизации — 2. Используя квадратичную формулу — 3. Заполнив квадрат — Давайте поймем это, решив это простое уравнение: Мы пытаемся сделать LHS,..

    Создание VR-миров с A-Frame
    Виртуальная реальность (и дополненная реальность) стали главными модными терминами в образовательных технологиях. С недорогими VR-гарнитурами, такими как Google Cardboard , и использованием..

    Демистификация рекурсии
    КОДЕКС Демистификация рекурсии Упрощенная концепция ошеломляющей О чем весь этот шум? Рекурсия, кажется, единственная тема, от которой у каждого начинающего студента-информатика..