【问题标题】:Construct a column getting elements from another table in R构造一列从 R 中的另一个表中获取元素
【发布时间】:2022-07-21 21:54:52
【问题描述】:

给定一个大表,其中有两个重要的列:

  1. 国家代码
  2. 时间
Name     Nation code     Time       Other
a        IT              2010       x
b        DE              2011       y
c        ES              2009       z

我想使用这两个指标构建另一个列,以从另一个表中获取数据,该表的构建如下

Nation code     Y2009     Y2010      Y2011
DE              200       100        300
ES              100       150        350
GB              200       250        50
IT              50        150        100

最终的结果应该如下

Name     Nation code     Time       Other       NewColumn
a        IT              2010       x           150
b        DE              2011       y           300
c        ES              2009       z           100

【问题讨论】:

  • 栈标签推荐系统不完善。您的 datatable 标记在这里不相关,因为(如果您将鼠标悬停在它上面)它太模棱两可并且真的不应该在 R 中使用。如果您的意思是 data.table 包,那么使用 data.table 标记。如果您的意思通常是data.frame,那么就有[data.frame] 标签(尽管不可否认,这并没有真正在SO 上添加太多上下文,大多数在这里回答的[r] 用户都精通框架。)跨度>

标签: r datatable


【解决方案1】:

要得到你想要的,你需要执行两个步骤:首先你需要一个长格式的df2(例如使用pivot_longer),然后你会用@987654323做一个左连接@(例如使用left_join)。

即:

library(dplyr)
library(tidyr)

df2_long <-
  df2 |> 
  pivot_longer(-Nation_code, names_prefix = "Y", names_to = "Time", values_to = "new_col") |>
  mutate(Time = as.numeric(Time))

# # A tibble: 12 × 3
# Nation_code  Time new_col
# <chr>       <dbl>   <dbl>
#   1 DE           2009     200
# 2 DE           2010     100
# 3 DE           2011     300
# 4 ES           2009     100
# 5 ES           2010     150
# 6 ES           2011     350
# 7 GB           2009     200
# 8 GB           2010     250
# 9 GB           2011      50
# 10 IT           2009      50
# 11 IT           2010     150
# 12 IT           2011     100

df1 |>
  left_join(df2_long, by = c("Nation_code", "Time"))

输出:

# A tibble: 3 × 5
  Name  Nation_code  Time Other new_col
  <chr> <chr>       <dbl> <chr>   <dbl>
1 a     IT           2010 x         150
2 b     DE           2011 y         300
3 c     ES           2009 z         100

数据:

library(readr)

df1 <- read_table("Name     Nation_code     Time       Other
a        IT              2010       x
b        DE              2011       y
c        ES              2009       z")

df2 <- read_table("Nation_code     Y2009     Y2010      Y2011
DE              200       100        300
ES              100       150        350
GB              200       250        50
IT              50        150        100")

【讨论】:

    【解决方案2】:
    library(tidyverse)
    
    df <- read_table("Name     Nation_code     Time       Other
    a        IT              2010       x
    b        DE              2011       y
    c        ES              2009       z")
    
    df1 <- read_table("Nation_code     Y2009     Y2010      Y2011
    DE              200       100        300
    ES              100       150        350
    GB              200       250        50
    IT              50        150        100")
    
    df1 <- df1 %>%  
      pivot_longer(-Nation_code, 
                   names_to = "Time", 
                   values_to = "NewColumn") %>%  
      mutate(Time = Time %>% str_remove_all("Y") %>%  
               as.numeric)
    
    df %>%  
      left_join(df1, by = c("Nation_code", "Time"))
    
    # A tibble: 3 x 5
      Name  Nation_code  Time Other NewColumn
      <chr> <chr>       <dbl> <chr>     <dbl>
    1 a     IT           2010 x           150
    2 b     DE           2011 y           300
    3 c     ES           2009 z           100
    

    【讨论】:

      【解决方案3】:

      base R(和reshape2

      reshape2::melt(df2, "Nation_code", variable.name = "Time", value.name = "NewColumn") |>
        transform(Time = as.integer(sub("\\D", "", Time))) |>
        merge(df1, by = c("Nation_code", "Time"), all.y = TRUE)
      #   Nation_code Time NewColumn Name Other
      # 1          DE 2011       300    b     y
      # 2          ES 2009       100    c     z
      # 3          IT 2010       150    a     x
      

      数据表

      # library(data.table)
      DT1 <- as.data.table(df1)
      DT2 <- as.data.table(df2)
      DT1[
        melt(DT2, "Nation_code", variable.name = "Time", value.name = "NewColumn"
          )[, Time := as.integer(sub("\\D", "", Time))],
        NewColumn := i.NewColumn, on = .(Nation_code, Time)][]
      #      Name Nation_code  Time  Other NewColumn
      #    <char>      <char> <int> <char>     <int>
      # 1:      a          IT  2010      x       150
      # 2:      b          DE  2011      y       300
      # 3:      c          ES  2009      z       100
      

      这是关于 SO 的两个常见问题的组合:

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2018-05-13
        • 1970-01-01
        相关资源
        最近更新 更多