Используя Tidyverse и каналы, как назначить фиксированные строки - PullRequest
1 голос
/ 14 марта 2020

С учетом этого кадра данных

X1          X2   
2001        NA
abc         10
def         12
xo          13
2002        NA
abc         10
efd         22
dd          23
2005        NA
a           30

Все годы имеют NA в X2. Моя цель состоит в том, чтобы этот фрейм данных стал

X1          X2        Date
abc         10        2001
def         12        2001
xo          13        2001
abc         10        2002
efd         22        2002
dd          23        2002
a           30        2005

То есть годы стали их собственным столбцом, а NA были отброшены

То, что я пытался

a = read_csv("given.csv")
a %>% mutate(Date = ifelse(is.na(X2), X1, NA)) 

Это превращает первый кадр данных в

X1          X2      Date
2001        NA      2001
abc         10      NA
def         12      NA
xo          13      NA
2002        NA      2002
abc         10      NA
efd         22      NA
dd          23      NA
2005        NA      2005
a           30      NA

Я не уверен, как заменить NA столбца даты на верхнее значение для каждого года. После этого я думаю, что я могу просто drop_na, и это будет, как я хотел бы это

Ответы [ 2 ]

0 голосов
/ 14 марта 2020

Другая опция:

library(dplyr)
library(zoo)

a %>% 
  mutate(Date = na.locf(case_when(is.na(X2) ~ X1))) %>%
  na.omit

Вывод:

    X1 X2 Date
2  abc 10 2001
3  def 12 2001
4   xo 13 2001
6  abc 10 2002
7  efd 22 2002
8   dd 23 2002
10   a 30 2005

Если вы хотите сбросить номера строк, просто используйте filter(!is.na(X2)) вместо na.omit.

PS Конечно, вы можете просто загрузить tidyverse и сделать что-то вроде:

library(tidyverse)

a %>% 
  mutate(Date = case_when(is.na(X2) ~ X1)) %>%
  fill(Date) %>%
  drop_na

.. однако обратите внимание, что fill довольно медленный по сравнению с функцией na.locf из zoo.

0 голосов
/ 14 марта 2020

Мы можем создать столбец группировки на основе вхождения элементов только чисел (\\d+) в «X1», получить кумулятивную сумму, создать «Date» как элемент first для «X1», ungroup и удалите строки NA

library(dplyr)
library(stringr)
a %>%
    group_by(grp = cumsum(str_detect(X1, '^\\d+$'))) %>% 
    mutate(Date = first(X1)) %>%
    ungroup %>% 
    select(-grp) %>%
    na.omit
# A tibble: 7 x 3
#  X1       X2 Date 
#  <chr> <int> <chr>
#1 abc      10 2001 
#2 def      12 2001 
#3 xo       13 2001 
#4 abc      10 2002 
#5 efd      22 2002 
#6 dd       23 2002 
#7 a        30 2005 

Или используя data.table с zoo

library(data.table)
library(zoo)
na.omit(setDT(a)[, Date := na.locf(fifelse(is.na(X2), X1, NA_character_))])

data

a <- structure(list(X1 = c("2001", "abc", "def", "xo", "2002", "abc", 
"efd", "dd", "2005", "a"), X2 = c(NA, 10L, 12L, 13L, NA, 10L, 
22L, 23L, NA, 30L)), class = "data.frame", row.names = c(NA, 
-10L))
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...