簡體   English   中英

通過將值附加到其他列的列表中來在dplyr中創建新列?

[英]Create a new column in dplyr by appending values to a list from other columns?

我想通過附加到以其他列的值為條件的列表中來創建新列。 如果可能的話,我想在dplyr這樣做。 樣本輸入和所需的輸出如下。

假設一個數據newdata

col1 col2 col3 col4
dog  cat  NA   NA
NA   cat  foo  bar
dog  NA   NA   NA
NA   cat  NA   NA

這是我想要的輸出,帶有新列newCol

col1 col2 col3 col4 newCol
dog  cat  NA   NA   (dog, cat)
NA   cat  foo  bar  (cat, foo, bar)
dog  NA   NA   NA   (dog)
NA   cat  NA   bar  (cat, bar)

我已經嘗試使用ifelsemutatecase_whenmutate ,但都不會允許拼接到列表中。 這是我對case_when嘗試(失敗):

newdata = newdata %>% mutate( 
    newCol = case_when(
        col1 == "dog" ~ c("dog"),
        col2 == "cat" ~ c(newCol, "cat"),
        col3 == "foo" ~ c(newCol, "foo"),
        col4 == "bar" ~ c(newcol, "dog")
        )
    )

我嘗試了類似的方法,對每列使用ifelse語句,但是也無法追加到列表中。

使用帶有collapse參數的na.omit()paste()解決方案:

apply(newdata, 1, 
      function(x) paste0("(", paste(na.omit(x), collapse = ", "), ")"))
[1] "(dog, cat)" "(cat, foo, bar)" "(dog)" "(cat)"

演示版

在最后的注釋中,我們顯示了此處使用的輸入數據。 就像在問題中一樣,只是我們在末尾添加了一行NA,以表明所有解決方案在這種情況下也適用。

我們同時顯示列表和字符列解決方案。 這個問題專門針對list,所以這是假定的期望輸出,但是如果打算將newCol作為字符向量,那么我們也將其顯示出來。

使用基礎功能非常容易做到這一點,我們首先要說明。 但是,盡管它涉及更多的代碼,我們還是在tidyverse中重做了它。

1)base我們可以這樣使用apply

reduce <- function(x) unname(x[!is.na(x)])
DF$newCol <- apply(DF, 1, reduce)

給出以下內容,其中newCol是其第一部分為c("dog", "cat")等的列表。

  col1 col2 col3 col4        newCol
1  dog  cat <NA> <NA>      dog, cat
2 <NA>  cat  foo  bar cat, foo, bar
3  dog <NA> <NA> <NA>           dog
4 <NA>  cat <NA> <NA>           cat
5 <NA> <NA> <NA> <NA>              

最后一行代碼可能是:

DF$newCol <- lapply(split(DF, 1:nrow(DF)), reduce)

問題是連接到一個列表,所以我假設newCol需要一個列表,但是如果需要一個字符串,則可以使用它作為reduce:

reduce_ch <- function(x) sprintf("(%s)", toString(x[!is.na(x)]))
apply(DF, 1, reduce_ch)

2)tidyverse或使用tpldyr / tidyr / tibble將其收集為長形,刪除NA,將其嵌套,將其排序回原始順序,然后將其與DF綁定在一起。

library(dplyr)
library(tibble)
library(tidyr)

DF %>%
   rownames_to_column %>%
   gather(colName, Value, -rowname) %>%
   na.omit %>%
   select(-colName) %>%
   nest(Value, .key = newCol) %>%
   arrange(rowname) %>%
   left_join(cbind(DF %>% rownames_to_column), .) %>% 
   select(-rowname)

給予:

  col1 col2 col3 col4        newCol
1  dog  cat <NA> <NA>      dog, cat
2 <NA>  cat  foo  bar cat, foo, bar
3  dog <NA> <NA> <NA>           dog
4 <NA>  cat <NA> <NA>           cat
5 <NA> <NA> <NA> <NA>          NULL

如果需要字符輸出,請改用以下命令:

DF %>%
   rownames_to_column %>%
   gather(colName, Value, -rowname) %>%
   select(-colName) %>%
   group_by(rowname) %>%
   summarize(newCol = sprintf("(%s)", toString(na.omit(Value)))) %>%
   ungroup %>%
   { cbind(DF, .) } %>%
   select(-rowname)

給予:

  col1 col2 col3 col4          newCol
1  dog  cat <NA> <NA>      (dog, cat)
2 <NA>  cat  foo  bar (cat, foo, bar)
3  dog <NA> <NA> <NA>           (dog)
4 <NA>  cat <NA> <NA>           (cat)
5 <NA> <NA> <NA> <NA>              ()

注意

輸入DF重現形式:

Lines <- "col1 col2 col3 col4
dog  cat  NA   NA
NA   cat  foo  bar
dog  NA   NA   NA
NA   cat  NA   NA
NA   NA   NA   NA"
DF <- read.table(text = Lines,  header = TRUE, as.is = TRUE)

這看起來像是tidyr::unite的用例。 最后,您仍然需要進行一些dplyr清理,但這現在應該可以進行。

library(tibble)
library(dplyr)
library(tidyr)

df <- tribble(~col1, ~col2, ~col3, ~col4,
              "dog", "cat", NA, NA,
              NA, "cat", "foo", "bar",
              "dog", NA, NA, NA,
              NA, "cat", NA, NA)

df %>%
  unite(newCol, col1, col2, col3, col4,
        remove = FALSE,
        sep = ', ') %>%
  # Replace NAs and "NA, "s with ''
  mutate(newCol = gsub('NA[, ]*', '', newCol)) %>%
  # Replace ', ' with '' if it is at the end of the line
  mutate(newCol = gsub(', $', '', newCol)) %>%
  # Add the parentheses on either side
  mutate(newCol = paste0('(', newCol, ')'))
#> # A tibble: 4 x 5
#>            newCol  col1  col2  col3  col4
#>             <chr> <chr> <chr> <chr> <chr>
#> 1      (dog, cat)   dog   cat  <NA>  <NA>
#> 2 (cat, foo, bar)  <NA>   cat   foo   bar
#> 3           (dog)   dog  <NA>  <NA>  <NA>
#> 4           (cat)  <NA>   cat  <NA>  <NA>

同樣出於價值,其他人也在討論這個問題

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM