Как создать столбец, который идентифицирует другой столбец, в котором изменяются значения строк?

#r

#r

Вопрос:

У меня есть data.frame в R с некоторыми столбцами с числовыми значениями. Я хочу определить столбцы, в которых значение строки изменяется в определенный момент. Например:

  A B C D E
 0 6 0 0 0
 0 6 0 1 -5
 0 0 0 2 4
 4 0 0 2 -1
  

Я хочу определить, для отрицательных строк в столбце E, имеют ли A, B, C или D изменение значения строки по сравнению с предыдущей строкой? Итак, для -5 в столбце E столбец, который я хотел бы идентифицировать, равен D, потому что его значение строки изменяется с 0 на 1, а для -1 в столбце E я бы хотел идентифицировать столбец A. Есть ли способ создать другой столбец, который идентифицирует A, B, C или D в качестве столбца изменения строки? Заранее благодарю

Комментарии:

1. возможно ли изменить 2 столбца?

Ответ №1:

Я полагаю, вы могли бы создать матрицу различий для первых 4 столбцов (используя ваш фрейм данных df ):

 df_diff <- rbind(0, diff(as.matrix(df[1:4])))
  

Что даст вам:

      A  B C D
[1,] 0  0 0 0
[2,] 0  0 0 1
[3,] 0 -6 0 1
[4,] 4  0 0 0
  

Затем, используя sapply с индексом для вашего фрейма данных и другой матрицы, вы можете выполнить следующее:

 df$F <- sapply(seq_len(nrow(df)), function(i) ifelse(df[i, 5] < 0, 
                                                     names(which(df_diff[i, ] != 0))[1], 
                                                     NA_character_))
  

Это проверит наличие отрицательных значений в столбце 5, и для отрицательных значений выберите первое найденное имя столбца с разницей, определенной в другой матрице (отличной от нуля). В противном случае будет вставлен NA . Новый столбец F будет содержать этот результат.

Вывод

   A B C D  E    F
1 0 6 0 0  0 <NA>
2 0 6 0 1 -5    D
3 0 0 0 2  4 <NA>
4 4 0 0 2 -1    A
  

Данные

 df <- structure(list(A = c(0, 0, 0, 4), B = c(6, 6, 0, 0), C = c(0, 
0, 0, 0), D = c(0, 1, 2, 2), E = c(0, -5, 4, -1), F = c(NA, "D", 
NA, "A")), row.names = c(NA, -4L), class = "data.frame")
  

Ответ №2:

Это определенно не самое элегантное решение, но оно должно работать:

 change <- c()

for(i in 1:nrow(df)) {
  if (df$E[i] >= 0) {
    change <- c(change, 'unchanged')
  } else {
    if (df$A[i]!=df$A[i-1]) {
      change <- c(change, 'A')
    } else if (df$B[i]!=df$B[i-1]) {
      change <- c(change, 'B')
    } else if (df$C[i]!=df$C[i-1]) {
      change <- c(change, 'C')
    } else if (df$D[i]!=df$D[i-1]) {
      change <- c(change, 'D')
    }
  }
}

df$Change <- change
  

Ответ №3:

 # This is your original dataframe
x <- data.frame(
"A" = c(0,0,0,4), 
"B" = c(6,6,0,0),
"C" = c(0,0,0,0),
"D" = c(0,1,2,2),
"E" = c(0,-5,0,-1))

# Finding the differences with previous row
new_x = data.frame(
"A" = c(0, abs(diff(x$A))),
"B" = c(0, abs(diff(x$B))),
"C" = c(0, abs(diff(x$C))),
"D" = c(0, abs(diff(x$D))),
"E" = x$E)

# max.col gives the position of column that is max.
new_x$R = names(new_x)[max.col(new_x[,1:4], "first")]
# filter out only rows where E is -ve
new_x[new_x$E<0,"R"]