Oto moje dane zabawki.

    df <- tibble::tribble(
    ~date1,      ~A Equity,  ~date2,          ~B Equity, ~date3,     ~C Equity,
    "1/29/2016",        35,  "10/31/2017",     67,       NA_character_,  NA_real_,
    "2/29/2016",        40,  "11/30/2017",     31,       NA_character_,  NA_real_,
    NA_character_,NA_real_,  "12/29/2017",     56,       NA_character_,  NA_real_)

Prawdziwy ma ponad 1000 kolumn i wiele więcej dat.

Chcę długie dane, dzięki czemu żądany wyjście ma tylko kolumny daty, var i wartości, jak pokazano poniżej:

desired_df <- tibble::tribble(
         ~date,   ~var,  ~value,
   "1/29/2016",  "A",      35,
   "2/29/2016",  "A",      40,
  "10/31/2017",  "B",      67,
  "11/30/2017",  "B",      31,
  "12/29/2017",  "B",      56)

Próbowałem tego, ale nie otrzymuję pożądanego wyniku:

df2 <- df %>% 
  pivot_longer(cols = contains("date"), names_to = "dates", values_to = "date") %>% 
  pivot_longer (cols = contains("Equity"), names_to = "var", values_to = "value") %>% 
  select(-dates) %>% 
  distinct() %>% 
  filter(!is.na(date))
1
Geet 9 marzec 2020, 14:55

2 odpowiedzi

Najlepsza odpowiedź

Jeśli names_to jest znakiem zawierającym specjalny .value, wartość values_to zostanie zignorowana, a nazwa kolumny wartości będzie pochodzić z części istniejących nazw kolumn.

library(tidyverse)

## extract stock names
stock <- sub("_Equity", "", grep("Equity$", names(df), value = T))

df %>%
  rename_at(vars(starts_with("date")), ~ str_c(stock, "_date")) %>%
  rename_at(vars(ends_with("Equity")), ~ str_c(stock, "_value")) %>%
  pivot_longer(everything(),
               names_to = c("var", ".value"),
               names_sep = "_",
               values_drop_na = TRUE)

# # A tibble: 5 x 3
#   var   date       value
#   <chr> <chr>      <dbl>
# 1 A     1/29/2016     35
# 2 B     10/31/2017    67
# 3 A     2/29/2016     40
# 4 B     11/30/2017    31
# 5 B     12/29/2017    56

Dane

df <- structure(list(date1 = c("1/29/2016", "2/29/2016", NA), A_Equity = c(35, 
40, NA), date2 = c("10/31/2017", "11/30/2017", "12/29/2017"), 
    B_Equity = c(67, 31, 56), date3 = c(NA_character_, NA_character_, 
    NA_character_), C_Equity = c(NA_real_, NA_real_, NA_real_
    )), row.names = c(NA, -3L), class = c("tbl_df", "tbl", "data.frame"))
6
Darren Tsai 20 wrzesień 2020, 11:29

BASE R Rozwiązanie przy użyciu reshape (tak, nadal tam jest).

setNames(
  na.omit(
    reshape(
      as.data.frame(df), direction="long", varying=1:6, sep="")), 
  c("var","date","value","id"))

    var       date value id
1.1   1  1/29/2016    35  1
2.1   1  2/29/2016    40  2
1.2   2 10/31/2017    67  1
2.2   2 11/30/2017    31  2
3.2   2 12/29/2017    56  3

A jeśli dane "Zabawki" ma więcej kolumn, zmień różne do:

grep("^[var|date]", names(df))
2
Edward 9 marzec 2020, 13:38