Создать новую переменную в датафрейме на основе условия в одном столбце, вытягивая из другого столбца?(Dplyr) - PullRequest
0 голосов
/ 16 мая 2018

У меня есть следующий фрейм данных:

    df <- structure(list(country = c("Ghana", "Eritrea", "Ethiopia", "Ethiopia", 
"Congo - Kinshasa", "Ethiopia", "Ethiopia", "Ghana", "Botswana", 
"Nigeria"), CommodRank = c(1L, 2L, 3L, 1L, 3L, 1L, 1L, 1L, 1L, 
1L), topCommodInCountry = c(TRUE, FALSE, FALSE, TRUE, FALSE, 
TRUE, TRUE, TRUE, TRUE, TRUE), Main_Commod = c("Gold", "Copper", 
"Nickel", "Gold", "Gold", "Gold", "Gold", "Gold", "Diamonds", 
"Iron Ore")), row.names = c(NA, -10L), class = c("grouped_df", 
"tbl_df", "tbl", "data.frame"), vars = "country", drop = TRUE, indices = list(
    8L, 4L, 1L, c(2L, 3L, 5L, 6L), c(0L, 7L), 9L), group_sizes = c(1L, 
1L, 1L, 4L, 2L, 1L), biggest_group_size = 4L, labels = structure(list(
    country = c("Botswana", "Congo - Kinshasa", "Eritrea", "Ethiopia", 
    "Ghana", "Nigeria")), row.names = c(NA, -6L), class = "data.frame", vars = "country", drop = TRUE, .Names = "country"), .Names = c("country", 
"CommodRank", "topCommodInCountry", "Main_Commod"))

df

            country CommodRank topCommodInCountry Main_Commod
1             Ghana          1               TRUE        Gold
2           Eritrea          2              FALSE      Copper
3          Ethiopia          3              FALSE      Nickel
4          Ethiopia          1               TRUE        Gold
5  Congo - Kinshasa          3              FALSE        Gold
6          Ethiopia          1               TRUE        Gold
7          Ethiopia          1               TRUE        Gold
8             Ghana          1               TRUE        Gold
9          Botswana          1               TRUE    Diamonds
10          Nigeria          1               TRUE    Iron Ore  

Я пытаюсь добавить еще один столбец, показывающий лучший товар (top CommodRank) для каждой страны в этом наборе данных, но я не уверен, как. Я могу пометить «topcommod» с помощью «Main_Commod», где CommodRank == 1, но я хочу скопировать это же значение в случаи, когда CommodRank! = 1. Глядя ниже, оба значения из Эфиопии в строках 3 и 4 должны читаться » Gold».

df %>% mutate(topcommod = ifelse(CommodRank == 1, Main_Commod, 'unknown'))


            country CommodRank topCommodInCountry Main_Commod topcommod
1             Ghana          1               TRUE        Gold      Gold
2           Eritrea          2              FALSE      Copper   unknown
3          Ethiopia          3              FALSE      Nickel   unknown
4          Ethiopia          1               TRUE        Gold      Gold
5  Congo - Kinshasa          3              FALSE        Gold   unknown
6          Ethiopia          1               TRUE        Gold      Gold
7          Ethiopia          1               TRUE        Gold      Gold
8             Ghana          1               TRUE        Gold      Gold
9          Botswana          1               TRUE    Diamonds  Diamonds
10          Nigeria          1               TRUE    Iron Ore  Iron Ore

В идеале я ищу решение dplyr, которое можно добавить в существующую длинную серию вызовов функции%>% pipe, но любое решение поможет.

Ответы [ 3 ]

0 голосов
/ 16 мая 2018

другой шаблон с dplyr ...

df %>% arrange(CommodRank) %>%
    mutate(topCommod = Main_Commod[1])
0 голосов
/ 16 мая 2018

Это не ответ, но очень многому научился из ответа @docendo discimus, мне потребовалась секунда, чтобы понять «если отрицательно» (!any(topCommodInCountry)), и мне было интересно, будет ли это только я, или это займет у моего компьютера секундучтобы сделать это тоже :)

Используя тот же набор данных, я рассмотрел идею сделать if else положительным.Сначала я проверил identical между двумя решениями:

identical(
  #Negative
  df %>% 
    mutate(topCom = if(!any(topCommodInCountry)) "unknown" 
           else Main_Commod[which.max(topCommodInCountry)]), 
  #Positive
  df %>% 
    mutate(topCom = if(any(topCommodInCountry)) Main_Commod[which.max(topCommodInCountry)] 
           else "unknown"))

[1] TRUE

Затем я проверил эталон двух:

require(rbenchmark)

benchmark("Negative" = {
  df %>% 
    mutate(topCom = if(!any(topCommodInCountry)) "unknown" 
           else Main_Commod[which.max(topCommodInCountry)])
},
"Positive" = {
  df %>% 
    mutate(topCom = if(any(topCommodInCountry)) Main_Commod[which.max(topCommodInCountry)] 
           else  "unknown")
},
replications = 10000,
columns = c("test", "replications", "elapsed",
            "relative", "user.self", "sys.self"))

Разница не такая большая, но япредполагая, что с большим набором данных это увеличится.

      test replications elapsed relative user.self sys.self
1 Negative        10000   12.59    1.015     12.44        0
2 Positive        10000   12.41    1.000     12.30        0 
0 голосов
/ 16 мая 2018

IIUC, есть несколько способов сделать это, например:

df %>% mutate(topCom = if(!any(topCommodInCountry)) "unknown" 
                       else Main_Commod[which.max(topCommodInCountry)])

# A tibble: 10 x 5
# Groups:   country [6]
   country          CommodRank topCommodInCountry Main_Commod topCom  
   <chr>                 <int> <lgl>              <chr>       <chr>   
 1 Ghana                     1 TRUE               Gold        Gold    
 2 Eritrea                   2 FALSE              Copper      unknown 
 3 Ethiopia                  3 FALSE              Nickel      Gold    
 4 Ethiopia                  1 TRUE               Gold        Gold    
 5 Congo - Kinshasa          3 FALSE              Gold        unknown 
 6 Ethiopia                  1 TRUE               Gold        Gold    
 7 Ethiopia                  1 TRUE               Gold        Gold    
 8 Ghana                     1 TRUE               Gold        Gold    
 9 Botswana                  1 TRUE               Diamonds    Diamonds
10 Nigeria                   1 TRUE               Iron Ore    Iron Ore

Относительно вопроса ОП в комментарии о том, как обрабатывать связи нескольких топовых товаров, вы можете сделать следующее:

df %>% 
  mutate(topCom = if(!any(topCommodInCountry)) "unknown" 
              else paste(unique(Main_Commod[topCommodInCountry]), collapse = "/"))

Если в стране имеется несколько уникальных лучших товаров, они будут вставлены в одну строку, разделенную /.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...