Непоследовательные результаты в применении - PullRequest
0 голосов
/ 03 апреля 2019

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

Взять данные dd:

dd <- structure(list(first = c("118751", "55627", NA), one = c(41006L, 
119098L, 109437L), two = c(118751L, 109016L, 109831L), three = c(122631L, 
104639L, 120634L), four = c(38017L, 118950L, 105440L), five = c(114826L, 
122047L, 124347L), six = c(109438L, 55627L, 118679L), seven = c(27094L, 
107044L, 122161L), eight = c(112473L, 116909L, 124363L), nine = c(120586L, 
114711L, 120509L)), row.names = c(NA, 3L), class = "data.frame")

dd
   first    one    two  three   four   five    six  seven  eight   nine
1 118751  41006 118751 122631  38017 114826 109438  27094 112473 120586
2  55627 119098 109016 104639 118950 122047  55627 107044 116909 114711
3   <NA> 109437 109831 120634 105440 124347 118679 122161 124363 120509

Теперь мы хотим найти строки, в которых число в столбце first равно числув столбце six (который является седьмым столбцом в кадре данных), используя apply:

apply(dd,1,function(x) as.integer(x["first"])==x[7])

    1     2     3 
FALSE FALSE    NA 

Этот результат явно ложный - 2 должно было дать TRUE.Как ни странно, если я запускаю ту же вещь ТОЛЬКО во втором ряду, я получаю правильный ответ:

apply(dd[2,],1,function(x) as.integer(x["first"])==x[7])

   2 
TRUE 

Я также пробовал другие подмножества - 1: 2, 2: 3 и даже c (1,3).Последний дает мне ожидаемый результат, в то время как первые два продолжают настаивать на FALSE для строки 2.

Если я опускаю apply, я получаю правильный ответ (независимо от подмножества):

as.integer(dd$first)==dd$six
[1] FALSE  TRUE    NA

Что, черт возьми, происходит?

Ответы [ 2 ]

2 голосов
/ 03 апреля 2019

Проблема в ваших типах данных. Ваш первый столбец character, остальные столбцы целые. Вы пытаетесь исправить это с помощью as.integer() внутри apply, но уже слишком поздно. apply работает с матрицами, а не с фреймами данных. Когда вы даете ему фрейм данных, он немедленно преобразуется в матрицу. Матрицы не могут иметь разные классы столбцов, и (как правило) character не может быть преобразовано в numeric, поэтому все ваши данные преобразуются в character.

Вот окно в это преобразование:

apply(dd, 1, print)
#       1        2        3       
# first "118751" "55627"  NA      
# one   " 41006" "119098" "109437"
# two   "118751" "109016" "109831"
# three "122631" "104639" "120634"
# four  " 38017" "118950" "105440"
# five  "114826" "122047" "124347"
# six   "109438" " 55627" "118679"
# seven " 27094" "107044" "122161"
# eight "112473" "116909" "124363"
# nine  "120586" "114711" "120509"

Вы можете видеть, что, к сожалению, также добавляются пробелы, что делает равенство неверным.

Вместо этого сначала преобразуйте столбец в правильный тип. Или, что еще лучше, вообще не беспокойтесь о apply:

# convert
dd[, "first"] = as.integer(dd[, "first"])

# apply now works
apply(dd, 1, function(x) x["first"] == x[7])
#     1     2     3 
# FALSE  TRUE    NA 

# but isn't this easier?
dd[, "first"] == dd[, "six"]
# [1] FALSE  TRUE    NA
1 голос
/ 03 апреля 2019

Обтекание x[7] в as.integer() решает вашу проблему

apply(dd,1,function(x) as.integer(x["first"])==as.integer(x[7]))

, потому что если вы запустите следующий код, вы увидите, что as.integer(x["first"]) и x[7] возвращают различные типы class, которыене сопоставимы.

apply(dd,1,function(x) return(list(class(as.integer(x["first"])), class(x[7]))))

$`1`
$`1`[[1]]
[1] "integer"

$`1`[[2]]
[1] "character"


$`2`
$`2`[[1]]
[1] "integer"

$`2`[[2]]
[1] "character"


$`3`
$`3`[[1]]
[1] "integer"

$`3`[[2]]
[1] "character"
...