Неожиданный возврат saply - матрицы списков? - PullRequest
1 голос
/ 18 апреля 2019

У меня есть функция, которая должна обновлять некоторые значения из кадра данных. Функция получает индекс строки изменяемых данных, фрейм данных, а также переменные. Эта функция вызывается sapply для изменения всех индексов. Я ожидаю, что матрица будет возвращать sapply, и я бы мог изменить свой базовый фрейм данных путем индексации. К сожалению, я не могу предоставить реальные данные, но следующие фиктивные данные повторяют проблему. Я не понимаю, почему это не работает. Возможно, причина в том, что матрица, возвращаемая sapply, не является "нормальной" матрицей целых чисел, но какая-то матрица списков?

Манекен-Dataframe:

data_test = data.frame(matrix(1:100, 10, 10))
names(data_test) = paste0("Var", 1:10)

# Var1 Var2 Var3 Var4 Var5 Var6 Var7 Var8 Var9 Var10
# 1     1   11   21   31   41   51   61   71   81    91
# 2     2   12   22   32   42   52   62   72   82    92
# 3     3   13   23   33   43   53   63   73   83    93
# 4     4   14   24   34   44   54   64   74   84    94
# 5     5   15   25   35   45   55   65   75   85    95
# 6     6   16   26   36   46   56   66   76   86    96
# 7     7   17   27   37   47   57   67   77   87    97
# 8     8   18   28   38   48   58   68   78   88    98
# 9     9   19   29   39   49   59   69   79   89    99
# 10   10   20   30   40   50   60   70   80   90   100

«нормальная» матрица для замены некоторых значений data_test на индексы:

data_replace = matrix(1:16, 4,4)

# [,1] [,2] [,3] [,4]
# [1,]    1    5    9   13
# [2,]    2    6   10   14
# [3,]    3    7   11   15
# [4,]    4    8   12   16

Это хорошо работает:

data_test[c("Var3", "Var4", "Var5", "Var6")][4:7,] = data_replace

# Var1 Var2 Var3 Var4 Var5 Var6 Var7 Var8 Var9 Var10
# 1     1   11   21   31   41   51   61   71   81    91
# 2     2   12   22   32   42   52   62   72   82    92
# 3     3   13   23   33   43   53   63   73   83    93
# 4     4   14    1    5    9   13   64   74   84    94
# 5     5   15    2    6   10   14   65   75   85    95
# 6     6   16    3    7   11   15   66   76   86    96
# 7     7   17    4    8   12   16   67   77   87    97
# 8     8   18   28   38   48   58   68   78   88    98
# 9     9   19   29   39   49   59   69   79   89    99
# 10   10   20   30   40   50   60   70   80   90   100

Dummy-функция для вызова sapply:

# just a test-function to be called by sapply. It multiplies all the temp_vars from temp_data in rows temp_index by 2
function_test = function(temp_index, temp_data = data_test, temp_vars = c("Var3", "Var4", "Var5", "Var6"))
{
  return(temp_data[temp_vars][temp_index,] * 2)
}

Вызов функции с использованием sapply для некоторых индексов строк

#function call 
temp_results = t(sapply(4:7, function_test))
data_test[c("Var3", "Var4", "Var5", "Var6")][4:7,]

# Var3 Var4 Var5 Var6
# 4    1    5    9   13
# 5    2    6   10   14
# 6    3    7   11   15
# 7    4    8   12   16

Попытка заменить некоторые значения data_test с помощью индексации (как и раньше), к сожалению, здесь не работает. Это дает мне следующую ошибку:

data_test[c("Var3", "Var4", "Var5", "Var6")][4:7,] = temp_results

# Warning message:
# In `[<-.data.frame`(`*tmp*`, 4:7, , value = list(Var3 = c(21, 22,  :
#   provided 16 variables to replace 4 variables

Некоторая информация об используемых данных. Они должны быть одинакового размера.

dim(data_test[c("Var3", "Var4", "Var5", "Var6")][4:7,])
# 4 4
dim(temp_results)
# 4 4
dim(data_replace)
# 4 4

class(temp_results)
# matrix
class(data_replace)
# matrix

Это странно для меня. Я не понимаю, что это значит.

apply(temp_results, 2, class)
# Var3   Var4   Var5   Var6 
# "list" "list" "list" "list" 
apply(data_replace, 2, class)
# "integer" "integer" "integer" "integer"

Я могу обойти эту проблему, используя temp_results = lapply вместо temp_results = sapply, а затем использовать функцию matrix(unlist(temp_results), 4, byrow = T), но все же я хотел бы понять, что здесь происходит с возвращением sapply.

Любой вклад был бы великолепен! Заранее спасибо

1 Ответ

1 голос
/ 18 апреля 2019

Заставьте вашу функцию возвращать значения в виде матрицы:

function_test <- function(temp_index, temp_data = data_test, temp_vars = c("Var3", "Var4", "Var5", "Var6"))
{
  return(as.matrix(temp_data[temp_vars][temp_index,] * 2))
}

Это должно работать так, как вы хотите.

...