фильтровать переменные для соединения двух информационных фреймов в разных измерениях - PullRequest
1 голос
/ 01 декабря 2019

Есть два кадра данных, которые я хочу соединить.

Так как у меня есть 2 измерения, чтобы отфильтровать значение из столбца второй таблицы, которое удовлетворяет некоторым условиям первой таблицы. Первый кадр данных выглядит так:

 letter   year  value
    A        2001   
    B        2002
    C        2003
    D        2004

второй:

       letter  2001  2002 2003 2004
        A         4     9    9   9
        B         6      7   6    6  
        C         2      3   5    8 
        D         1       1  1    1

, что дает мне что-то вроде этого

letter year    value
A       2001    4
B       2002    7
C       2003    5
D       2004    1

thank all of you

Ответы [ 3 ]

0 голосов
/ 01 декабря 2019

Другой вариант в tidyverse - сначала перевести ваши значения данных в более длинный фрейм данных (данные из ответа @ akrun):

df2.long <- df2 %>% 
  pivot_longer(`2001`:`2004`, names_to = 'year', values_to = 'value')

# A tibble: 16 x 3
   letter year  value
   <chr>  <chr> <int>
 1 A      2001      4
 2 A      2002      9
 3 A      2003      9
 4 A      2004      9
 5 B      2001      6
 6 B      2002      7
 7 B      2003      6
 8 B      2004      6
 9 C      2001      2
10 C      2002      3
...

И затем выполнить inner_join к фрейму данных, содержащему желаемые комбинации букв и годов:

df.final <- df2.long %>% 
  mutate(year = as.numeric(year)) %>% 
  inner_join(df1)

  letter  year value
  <chr>  <dbl> <int>
1 A       2001     4
2 B       2002     7
3 C       2003     5
4 D       2004     1
0 голосов
/ 01 декабря 2019

Решение Base R:

# Reshape your dataframe from wide to long: 

df3 <- reshape(df2,
               direction = "long",
               idvar = "letter",
               varying = c(names(df2)[names(df2) != "letter"]),
               v.names = "Value",
               timevar = "Year",
               times = names(df2)[names(df2) != "letter"],
               new.row.names = 1:(nrow(df2) * length(names(df2)[names(df2) != "letter"]))
              )

# Inner join the long_df with the first dataframe: 

df_final <- merge(df1[,c(names(df1) != "Value")], df3, by = intersect(colnames(df1), colnames(df3)))

Решение Tidyverse (немного расширяется по решению @jdobres ниже):

lapply(c("dplyr", "tidyr"), require, character.only = TRUE)

df3_long <- 

  df2 %>% 

  pivot_longer(`2001`:`2004`, names_to = 'year', values_to = 'value') %>% 

  mutate(year = as.numeric(year)) %>% 

  inner_join(., df1, by = intersect(colnames(df1, df2)))

Данные:

df1 <-
  structure(list(letter = c("A", "B", "C", "D"), year = 2001:2004),
            class = "data.frame",
            row.names = c(NA,-4L))

df2 <-
  structure(
    list(
      letter = c("A", "B", "C", "D"),
      `2001` = c(4L,
                 6L, 2L, 1L),
      `2002` = c(9L, 7L, 3L, 1L),
      `2003` = c(9L, 6L, 5L,
                 1L),
      `2004` = c(9L, 6L, 8L, 1L)
    ),
    class = "data.frame",
    row.names = c(NA,-4L)
  )
0 голосов
/ 01 декабря 2019

Один из вариантов - индекс row/column. Здесь индекс строки может быть последовательностью строк, в то время как индекс столбца мы получаем из match в столбце 'year' первых данных с именами столбца second, cbind в индексах для создания matrix ('m1 ') и используйте его для извлечения значений из второго набора данных и назначения их столбцу' value 'в первых данных

i1 <- seq_len(nrow(df1))
j1 <- match(df1$year, names(df2)[-1])
m1 <- cbind(i1, j1)
df1$value <- df2[-1][m1]
df1
#   letter year value
#1      A 2001     4
#2      B 2002     7
#3      C 2003     5
#4      D 2004     1

Для конкретного примера извлекаемый шаблон выглядит как diag В этом случае мы также можем использовать

df1$value <- diag(as.matrix(df2[-1])) 

data

df1 <- structure(list(letter = c("A", "B", "C", "D"), year = 2001:2004),
class = "data.frame", row.names = c(NA, 
-4L))

df2 <- structure(list(letter = c("A", "B", "C", "D"), `2001` = c(4L, 
6L, 2L, 1L), `2002` = c(9L, 7L, 3L, 1L), `2003` = c(9L, 6L, 5L, 
1L), `2004` = c(9L, 6L, 8L, 1L)), class = "data.frame", 
row.names = c(NA, 
-4L))
...