Создание новых строк в кадре данных с использованием значений столбцов - PullRequest
2 голосов
/ 11 апреля 2019

Я пытаюсь отформатировать грязный фрейм данных в R, создавая новые строки из значений столбцов. Фрагмент данных выглядит следующим образом.

id  producer  pcountry  collaborator  ccountry   val
1    J&J       USA        Pfizer       USA       25

2    Biodiem   AUS        PhaseBio     USA       65
                          GeneScience  China     

3    Shire     Ireland       N/A        N/A      54

4    Sanofi    France        N/A        N/A      64

По сути, я хочу использовать значения в последних двух столбцах для создания новых строк в кадре данных. Пока у меня есть этот код, использующий пакет splitstackshape.

df2 <- cSplit(df, 4, "\r", "long")

Это делает работу для записей, которые имеют более одного значения в столбце соавтора (как строка 2 выше). Использование моего кода дает мне следующее: `

id  producer  pcountry  collaborator  ccountry   val
1    J&J       USA        Pfizer       USA       25

2    Biodiem   AUS        PhaseBio     USA       65
                                       China     

3    Biodiem   AUS        Genescience  USA       65
                                       China

4    Shire     Ireland       N/A        N/A      54

5    Sanofi    France        N/A        N/A      64

Однако есть еще кое-что, что я хочу сделать с данными, с которыми я борюсь. Я хочу, чтобы значения столбца соавтора совпадали со значениями столбца ccountry, поэтому строка 3 здесь будет иметь значение China в столбце ccountry, а строка 2 будет иметь USA. Я попытался добавить оба столбца в код, например, df2 <- cSplit(df, c(4,5), "\r", "long"), но это только делает большой беспорядок.

Наконец, поскольку код только создает новые записи с использованием разделителя новой строки, он игнорирует те, которые имеют только 1 значение (например, строку 1), потому что у них нет новых строк. Я хочу, чтобы они тоже были включены.

Есть ли способ изменить этот код для выполнения этих 2 дополнительных шагов, или мне нужно написать функцию для этого?

РЕДАКТИРОВАТЬ: Это фрагмент данных

     id producer pcountry collaborator              ccountry         val
  <dbl> <chr>    <chr>    <chr>                     <chr>          <dbl>
1     1 J&J      USA      Pfizer                    USA               25
2     2 Biodiem  AUS      "PhaseBio\r\nGenescience" "USA\r\nChina"    65
3     3 Shire    Ireland  NA                        NA                54
4     4 Sanofi   France   NA                        NA                64
structure(list(id = c(1, 2, 3, 4), producer = c("J&J", "Biodiem", 
"Shire", "Sanofi"), pcountry = c("USA", "AUS", "Ireland", "France"
), collaborator = c("Pfizer", "PhaseBio\r\nGenescience", NA, 
NA), ccountry = c("USA", "USA\r\nChina", NA, NA), val = c(25, 
65, 54, 64)), row.names = c(NA, -4L), class = c("tbl_df", "tbl", 
"data.frame"))

и это ожидаемый результат

     id producer pcountry collaborator ccountry   val
  <dbl> <chr>    <chr>    <chr>        <chr>    <dbl>
1     1 J&J      USA      NA           NA          25
2     2 J&J      USA      Pfizer       USA         25
3     3 Biodiem  AUS      NA           NA          65
4     4 Biodiem  AUS      PhaseBio     USA         65
5     5 Biodiem  AUS      Genescience  China       65
6     6 Shire    Ireland  NA           NA          54
7     7 Sanofi   France   NA           NA          64
structure(list(id = c(1, 2, 3, 4, 5, 6), producer = c("J&J", 
"J&J", "Biodiem", "Biodiem", "Biodiem", "Shire"), pcountry = c("USA", 
"USA", "AUS", "AUS", "AUS", "Ireland"), collaborator = c(NA, 
"Pfizer", NA, "PhaseBio", "Genescience", NA), ccountry = c(NA, 
"USA", NA, "USA", "China", NA), val = c(25, 25, 65, 65, 65, 54
)), row.names = c(NA, -6L), class = c("tbl_df", "tbl", "data.frame"
)) 

Ответы [ 2 ]

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

Рассмотрим базовый подход R с использованием strsplit в процессе группировки by:

# BUILD LIST OF SUBSET DFs WITH EXPANDED ROWS
df_list <- by(df, df[c("id", "producer", "pcountry", "val")], function(sub)
    data.frame(id = sub$id[1],
               producer = sub$producer[1],
               pcountry = sub$pcountry[1],
               collaborator = c(unlist(strsplit(as.character(sub$collaborator), "\r\n")[1]), NA),
               ccountry = c(unlist(strsplit(as.character(sub$ccountry), "\r\n")[1]), NA),
               val = sub$val[1])
)

# APPEND SUBSETS
final_df <- unique(do.call(rbind, df_list))

# RE-ORDER ROWS AND RESET ROW NAMES
final_df <- with(final_df, final_df[order(id, producer, pcountry, val),])
row.names(final_df) <- NULL

final_df
#   id producer pcountry collaborator ccountry val
# 1  1      J&J      USA       Pfizer      USA  25
# 2  1      J&J      USA         <NA>     <NA>  25
# 3  2  Biodiem      AUS     PhaseBio      USA  65
# 4  2  Biodiem      AUS  Genescience    China  65
# 5  2  Biodiem      AUS         <NA>     <NA>  65
# 6  3    Shire  Ireland         <NA>     <NA>  54
# 7  4   Sanofi   France         <NA>     <NA>  64

Rextester demo

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

Это супер просто с tidyr:

require(tidyr)
separate_rows(df, collaborator,ccountry, sep="\r\n")

# A tibble: 5 x 6
     id producer pcountry collaborator ccountry   val
  <dbl> <chr>    <chr>    <chr>        <chr>    <dbl>
1     1 J&J      USA      Pfizer       USA         25
2     2 Biodiem  AUS      PhaseBio     USA         65
3     2 Biodiem  AUS      Genescience  China       65
4     3 Shire    Ireland  NA           NA          54
5     4 Sanofi   France   NA           NA          64

Если вам нужны все эти дополнительные строки с NA для соавтора и ccountry, вы можете сделать это:

require(tidyr)
require(dplyr)
df %>% mutate(collaborator=ifelse(is.na(collaborator), NA, paste0("\r\n",collaborator)), 
    ccountry=ifelse(is.na(ccountry), NA, paste0("\r\n",ccountry))) %>% # Create extra rows before non NA rows
  separate_rows(collaborator,ccountry, sep="\r\n") %>% 
  mutate(collaborator=ifelse(collaborator=="",NA,collaborator), 
    ccountry=ifelse(ccountry=="", NA, ccountry)) # change empty strings to NAs
# A tibble: 7 x 6
     id producer pcountry collaborator ccountry   val
  <dbl> <chr>    <chr>    <chr>        <chr>    <dbl>
1     1 J&J      USA      NA           NA          25
2     1 J&J      USA      Pfizer       USA         25
3     2 Biodiem  AUS      NA           NA          65
4     2 Biodiem  AUS      PhaseBio     USA         65
5     2 Biodiem  AUS      Genescience  China       65
6     3 Shire    Ireland  NA           NA          54
7     4 Sanofi   France   NA           NA          64
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...