2016-04-29 2 views
1

У меня есть это два data.table sR: Как игнорировать определенное значение на PMIN

DT <- data.table(name = c("a","b","c","d"), 
       "850Hz" = c(0,1,1,0), 
       "1800Hz" = c(2,0,2,0), 
       "2100Hz" = c(0,3,0,3), 
       "2600Hz" = c(4,0,0,4)) 
Info <- data.table(Freq = c("850Hz", "1800Hz", "2100Hz", "2600Hz"), Rng = c(3000, 2000, 1800, 1000)) 

Я хочу, чтобы создать новый столбец под названием «Range» в DT, исходя для каждой строки, как следует: Если строка содержит число, отличное от 0 в столбце «850 Гц», тогда следует учитывать значение 3000 (согласно ассоциации, установленной между «850 Гц» и 3000 в data.table Info). Затем, если в столбце «1800 Гц» есть ненулевое число, оно должно учитывать значение 2000 и так далее для остальных двух столбцов. В конце он должен рассчитать максимум всех рассмотренных значений для этой строки и записать это в новый столбец «Диапазон». И так далее для остальных строк.

Кто-то предложил мне использовать этот кусок кода:

Info[, { 
    DT[, Range := pmax(Range, (get(Freq) != 0) * Rng, na.rm = TRUE)] 
    NULL 
}, by = Freq] 

Я не понимаю, как это работает, но это делает работу. Мой вопрос: почему, если бы я хотел иметь МИНИМУМ рассмотренных значений для каждой строки вместо максимума? Если я использую pmin, для этого конкретного примера все значения в столбце «Диапазон» будут равны 0, потому что делает, рассмотрим случаи, когда значение равно 0 в столбцах («850 Гц» и т. Д.), И я полагаю, что он умножается что нуль на соответствующее значение. Мне нужно сказать, чтобы игнорировать нули в этих четырех столбцах. Как?


Возможный ответ будет конвертировать все нули в этих столбцах в N/A-х, а затем с помощью na.rm = TRUE. Но мне трудно понять, как сделать эту выборочную замену. Количество рассмотренных колонок (850 Гц, 1800 Гц, 2100 Гц, 2600 Гц в этом примере) может быть меньше 4. Это связано с тем, что в зависимости от данных может отсутствовать один или несколько из этих четырех столбцов. Мне нужно будет рассмотреть все столбцы в DT, имя которых существует в векторе Info [, Freq]. Затем измените все 0 только в этих столбцах, для N/A. Я пытаюсь и терпеть неудачу каждый раз.

+1

Все было бы проще, если бы вы решили работать с данными, как 'DT2 = растопить (DT, ID = "имя", variable.name = "Freq") [значение! = 0] ', и в этом случае вы могли бы« DT2 [Info, Rng: = i.Rng, on = «Freq»] », а затем, если вам действительно нужно ...' cbind (dcast (DT2, name ~ Freq), dcast (DT2, name ~., Value.var = "Rng", fun = list (min, max)) [, name: = NULL]) '. Я также предлагаю прочитать статью о чистых данных о хадли: http://vita.had.co.nz/papers/tidy-data.pdf – Frank

+1

Хорошо работает, спасибо. Только два вопроса, в этой части «i.Rng» есть ли способ косвенно сделать ссылку на имя этого столбца? то есть 'colnames (Info) [2]'. Кажется, это не работает, когда я просто добавляю это после 'i.'Также есть ли способ избавиться от этих' _' после 'min' и 'max' в именах новых столбцов? – JAR

+0

Часть 'i.' является необязательной, фактически (используется для устранения неоднозначности, если объединенные таблицы имеют столбцы с тем же именем). Вы можете просто написать «Rng». Обычно я включаю его только для того, чтобы напомнить себе, что столбец исходит из 'i' в' x [i] 'merge. Во всяком случае, я добавил еще один способ (информация 'Info_cols'). – Frank

ответ

1

Я хотел бы сохранить основные данные в длинном формате:

DT_long = melt(DT, id="name", variable.name="Freq")[value != 0] 

и, возможно, добавить Rng столбец из Info

DT_long[Info, Rng := i.Rng, on="Freq"] 
# or 
Info_cols = setdiff(names(Info), "Freq") 
DT_long[Info, (Info_cols) := mget(Info_cols), on="Freq"] 

Чтобы отобразить сводку в широком формате, вы можете использовать dcast:

res = cbind( 
    dcast(DT_long, name ~ Freq), 
    dcast(DT_long, name ~ ., value.var = "Rng", fun = list(min, max))[, name := NULL] 
) 

    name 850Hz 1800Hz 2100Hz 2600Hz Rng_min_. Rng_max_. 
1: 1 NA  2  NA  4  1000  2000 
2: 2  1  NA  3  NA  1800  3000 
3: 3  1  2  NA  NA  2000  3000 
4: 4 NA  NA  3  4  1000  1800 

К сожалению, я не знаю w быстрый способ избавиться от завершающего _. в последних двух столбцах; возможно, эта функция будет добавлена ​​позже. Есть различные обходные пути, как

res = cbind( 
    dcast(DT_long, name ~ Freq), 
    DT_long[, c(Rng = list(min = min(Rng), max = max(Rng))), keyby=name][, name := NULL] 
) 
+0

Я попытался использовать его в своем реальном коде, и это не сработало, потому что DT имеет столбцы символов: – JAR

+0

Я попытался использовать его в своем реальном коде, и это не сработало, потому что DT имеет столбцы символов: 'Warning сообщение: В таблице melt.data.table (Towers, id = "TOWERS_ID", variable.name = "Frequency"): 'measure.vars' [LATITUDE, LONGITUDE, STATE, COUNTY, DISTRICT, 850Hz, 1800Hz, 2100Hz, 2600Hz] не все одного типа. По порядку иерархии столбец значений расплавленных данных будет иметь тип «символ». Все измерительные переменные, не относящиеся к типу «характер», будут принудительно применены. Проверьте детали в? Melt.data.table для получения дополнительной информации о принуждении. Я собираюсь изменить DT в своем вопросе, чтобы он был похож на мою проблему. – JAR

+0

Редактирование: ответ на последний вопрос - это просто объединение между нужными столбцами в 'DT' и' res' ... – JAR

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