如果一列中的值与变量名称的一部分匹配,则基于多列创建新变量

Create new variables based on multiple columns if value in one column match part of variable name

我对 R 很陌生,所以请保持温柔。

我有一个包含多个列的数据集,这些列重复测量了好几年。 我有 ID 变量,用于标识与这些措施相关的每一行的特定个人。

我还有一个变量,每行包含一年。

所以我的数据看起来像这样

ID Y2005_N0X Y2006_N0X Y2007_N0X Y2008_N0X Y2005_N06 Y2006_N06 Y2007_N06 Y2008_N0X YEAR
1 5 6 7 8 9 94 29 69 2005
2 6 7 8 9 9 39 59 39 2007

等等...

我想创建一个新列,为 ID 1 使用 2005 年的值,为 ID 2 使用 2007 年的值,并将这个新列命名为 prioryear_N0X。

我有几个这样的列,所以我想创建一个命令来根据这些条件生成多个新列,这样我就会得到一个名为 prioryear_N1X、prioryear_N06 的新列,依此类推向前。 ID 列完好无损也很重要。

在此之后,我还想创建名为 thisyear_N0X 的新列等等,这些列采用 YEAR+1 中的值(例如 2004+1=2005)并匹配当前名为 [=44 的变量=]等等。

ID Y2005_N0X Y2006_N0X Y2007_N0X Y2008_N0X Y2005_N06 Y2006_N06 Y2007_N06 Y2008_N0X YEAR prioryear_N0X prioryear_N06 thisyear_N0X thisyear_N06
1 5 6 7 8 9 94 29 69 2005 5 9 6 94
2 6 7 8 9 9 39 59 39 2007 8 59 9 39

建议?


如果我有同样以 R 开头的变量,我该如何使用该命令?

我尝试了以下方法,但收到错误消息。

df %>%
pivot_longer(cols = -c(ID, YEAR), names_to = c("header_year", ".value"), names_pattern = "Y(\d+)_(\w+)", names_transform = list(header_year = as.integer)) %>%
group_by(ID) %>%
mutate(across(starts_with("N", "R"), function(x) { x[YEAR == header_year] }, .names = "prioryear_{.col}"),
across(starts_with("N", "R"), function(x) { x[YEAR + 1 == header_year] }, .names = "thisyear_{.col}")) %>%
pivot_wider(id_cols = c(ID, YEAR, starts_with("prioryear"), starts_with("thisyear")), names_from = header_year, values_from = starts_with("N", "R"))

这是一种使用 tidyverse 的方法。您可以使用 pivot_longer 输入长格式,然后 mutate 根据以“N”开头的列动态创建新列。这包括两个新列,一列 header 年份与 YEAR 列匹配,一列与 YEAR + 1 匹配。最后,您可以将数据放入宽格式,这样类似于您的想要 table.

library(tidyverse)

df %>%
  pivot_longer(cols = -c(ID, YEAR), names_to = c("header_year", ".value"), names_pattern = "Y(\d+)_(\w+)", names_transform = list(header_year = as.integer)) %>%
  group_by(ID) %>%
  mutate(across(starts_with("N"), function(x) { x[YEAR == header_year] }, .names = "prioryear_{.col}"),
         across(starts_with("N"), function(x) { x[YEAR + 1 == header_year] }, .names = "thisyear_{.col}")) %>%
  pivot_wider(id_cols = c(ID, YEAR, starts_with("prioryear"), starts_with("thisyear")), names_from = header_year, values_from = starts_with("N"))

输出

     ID  YEAR prioryear_N0X prioryear_N06 thisyear_N0X thisyear_N06 N0X_2005 N0X_2006 N0X_2007 N0X_2008 N06_2005 N06_2006 N06_2007 N06_2008
  <int> <int>         <int>         <int>        <int>        <int>    <int>    <int>    <int>    <int>    <int>    <int>    <int>    <int>
1     1  2005             5             9            6           94        5        6        7        8        9       94       29       69
2     2  2007             8            59            9           39        6        7        8        9        9       39       59       39

我想我解决了。我错过了在使用多个匹配项时必须包含 c。

df %>%
    pivot_longer(cols = -c(ID, YEAR), names_to = c("header_year", ".value"), names_pattern = "Y(\d+)_(\w+)", names_transform = list(header_year = as.integer)) %>%
    group_by(ID) %>%
    mutate(across(starts_with(c("N", "R")), function(x) { x[YEAR == header_year] }, .names = "prioryear_{.col}"),
           across(starts_with(c("N", "R")), function(x) { x[YEAR + 1 == header_year] }, .names = "thisyear_{.col}")) %>%
    pivot_wider(id_cols = c(ID, YEAR, starts_with("prioryear"), starts_with("thisyear")), names_from = header_year, values_from = starts_with(c("N", "R")))