Как повторить функцию для всех строк для каждого столбца в R - PullRequest
3 голосов
/ 05 мая 2020

У меня есть df со значениями 150 строк, и я хотел бы, чтобы R было l oop или иным образом повторить следующее для каждой строки и столбца в df;

пример данных

df <- data.frame('criteria1' = c('x','1', 'X', '', 'X'), "criteria2" = c('y','3', '', 'X', ''), "criteria3" = c('y','7', '', 'X', 'X'))

Если X появляется в строке, я хотел бы, чтобы функция брала значения из двух первых строк и вставляла их вместе с '=' между ними. Следующее отлично работает для первого столбца

df$criteria1 <- ifelse(df$criteria1 == 'X', paste(df$criteria1 [1], '=', df$criteria1 [2]),'')
head(df)

Проблема в том, что когда я пытаюсь сделать это для всех столбцов в фрейме данных

df[] <- lapply(df, function(x) ifelse(df$x== 'X', paste(x[1], '=', x[2]),''))

Все ячейки становятся NA. Я пробовал использовать разные версии приведенного выше кода, но ничего не дает ожидаемого результата:

head(data.frame('criteria1' = c('x','1', 'x=1', '', 'x=1'), "criteria2" = c('y','3', '', 'y=3', ''), "criteria3" = c('y','7', '', 'y=7', 'y=7')))

Ответы [ 3 ]

2 голосов
/ 05 мая 2020

Используйте sapply вместо lapply ... есть много ссылок на разницу между ними, но я считаю, что проблема связана с тем, что ifelse применяется к вектору, а не к списку, и поэтому вы не может передать его lapply.

sapply(df, function(x) ifelse(x == 'X', paste(x[[1]], '=', x[[2]]),''))
2 голосов
/ 05 мая 2020

A dplyr решение:

EDIT

На основе комментария @Chuk P (см. Ниже) следующее редактирование ответа:

 df %>% 
   mutate_all(~ifelse(.=="X",paste0(.[[1]],"=",.[[2]]),""))
  criteria1 criteria2 criteria3
1                              
2                              
3       x=1                    
4                 y=3       y=7
5       x=1                 y=7

Это сопоставимо с выводом ниже:

ifelse(df$criteria1 == 'X', paste(df$criteria1 [1], '=', df$criteria1 [2]),'')
[1] ""      ""      "x = 1" ""      "x = 1"

Исходный ответ (см. Комментарии, оставленный здесь ответ на случай, если он может быть полезен в будущем)

df %>% 
   mutate_all(~ifelse(.%in%c(letters,LETTERS),paste0(.,"=",.[grep("\\d",.)]),.))

Или используя dplyr> = 0.8.89.9000:

df %>% 
  mutate(across(everything(),~ifelse(.%in%c(letters,LETTERS),
                                     paste0(.,"=",.[grep("\\d",.)]),.)))

Результат:

   criteria1 criteria2 criteria3
    1       x=1       y=3       y=7
    2         1         3         7
    3       X=1                    
    4                 X=3       X=7
    5       X=1                 X=7

Если вам нужны пробелы:

 df %>% 
   mutate_all(~ifelse(.%in%c(letters),paste0(.,"=",.[grep("\\d",.)]),.[!.%in%LETTERS]))
  criteria1 criteria2 criteria3
1       x=1       y=3       y=7
2         1         3         7
3                              
4         x                   y
5         1         y         7

ПРИМЕЧАНИЕ :

Для этого могут существовать более простые методы. Это сделано для разнообразия ответов.

1 голос
/ 05 мая 2020

Здесь вам нужно использовать mapply, т.е.

df[] <- mapply(function(x, y)replace(x, x == 'X', y), df, paste(df[1,], df[2,], sep = '='))

, что дает

  criteria1 criteria2 criteria3
1         x         y         y
2         1         3         7
3       x=1                    
4                 y=3       y=7
5       x=1                 y=7
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...