我有使用gather从宽转换为长的代码,但我必须逐列执行此操作。我想使用 pivot_longer 将宽多列收集到多个长列中,而不是逐列。
例如,列 hf_1、hf_2、hf_3、hf_4、hf_5、hf_6 需要转换为 2 列(hf_com - 此列具有来自宽 hf 列的值 1,2,3,4,5,6)和 (hf_com_freq -此列的值为 1)。
对于列 ac_1、ac_2、ac_3、ac_4、ac_5、ac_6,同样需要发生。这些列需要转换为 2 列(ac_com - 此列的值来自宽 ac 列,值为 1,2,3,4,5,6)和(ac_com_freq - 此列的值为 1)。
列 cs_1、cs_2、cs_3、cs_4、cs_5、cs_6、cs_7、cs_8 也需要发生同样的情况。这些列需要转换为 2 列(cur_sal - 此列的值来自宽 cs 列,值为 1,2,3,4,5,6,7,8)和(curr_sal_freq - 此列的值为 1)。
列 se_1、se_2、se_3、se_4、se_5、se_6、se_7、se_8 也需要发生同样的情况。这些列需要转换为 2 列(exp_sal - 此列的值是 1,2,3,4,5,6,7,8 来自宽 se 列)和(exp_sal_freq - 此列的值为 1)
我试过看:
和:
但我无法获得我需要的多个更长的列。
这是输入数据:
structure(list(np_id = c("81", "83", "85", "88", "1", "2"), np_look_work = c("yes",
"yes", "yes", "yes", "yes", "yes"), np_current_work = c("no",
"yes", "no", "no", "no", "no"), np_before_work = c("no", "NULL",
"yes", "yes", "yes", "yes"), np_keen_move = c("yes", "yes", "no",
"no", "no", "no"), np_city_size = c("village", "more than 500k inhabitants",
"more than 500k inhabitants", "village", "city up to 20k inhabitants",
"100k - 199k inhabitants"), np_gender = c("male", "female", "female",
"male", "female", "male"), np_age = c("18 - 24 years", "18 - 24 years",
"more than 50 years", "18 - 24 years", "31 - 40 years", "more than 50 years"
), np_education = c("secondary", "vocational", "secondary", "secondary",
"secondary", "secondary"), hf_1 = c(NA, NA, NA, "1", "1", "1"
), hf_2 = c(NA, "1", "1", NA, NA, NA), hf_3 = c(NA_character_,
NA_character_, NA_character_, NA_character_, NA_character_, NA_character_
), hf_4 = c(NA_character_, NA_character_, NA_character_, NA_character_,
NA_character_, NA_character_), hf_5 = c(NA_character_, NA_character_,
NA_character_, NA_character_, NA_character_, NA_character_),
hf_6 = c(NA_character_, NA_character_, NA_character_, NA_character_,
NA_character_, NA_character_), ac_1 = c(NA, NA, NA, NA, NA,
"1"), ac_2 = c(NA, "1", "1", NA, "1", NA), ac_3 = c(NA, NA,
NA, NA, "1", NA), ac_4 = c(NA_character_, NA_character_,
NA_character_, NA_character_, NA_character_, NA_character_
), ac_5 = c(NA_character_, NA_character_, NA_character_,
NA_character_, NA_character_, NA_character_), ac_6 = c(NA_character_,
NA_character_, NA_character_, NA_character_, NA_character_,
NA_character_), cs_1 = c(NA_character_, NA_character_, NA_character_,
NA_character_, NA_character_, NA_character_), cs_2 = c(NA,
"1", "1", NA, "1", NA), cs_3 = c(NA, NA, NA, NA, NA, "1"),
cs_4 = c(NA, NA, NA, "1", NA, NA), cs_5 = c(NA_character_,
NA_character_, NA_character_, NA_character_, NA_character_,
NA_character_), cs_6 = c(NA_character_, NA_character_, NA_character_,
NA_character_, NA_character_, NA_character_), cs_7 = c(NA_character_,
NA_character_, NA_character_, NA_character_, NA_character_,
NA_character_), cs_8 = c(NA_character_, NA_character_, NA_character_,
NA_character_, NA_character_, NA_character_), se_1 = c(NA,
NA, "1", "1", NA, NA), se_2 = c(NA, NA, NA, NA, "1", NA),
se_3 = c(NA, "1", NA, NA, "1", "1"), se_4 = c(NA_character_,
NA_character_, NA_character_, NA_character_, NA_character_,
NA_character_), se_5 = c(NA_character_, NA_character_, NA_character_,
NA_character_, NA_character_, NA_character_), se_6 = c(NA_character_,
NA_character_, NA_character_, NA_character_, NA_character_,
NA_character_), se_7 = c(NA_character_, NA_character_, NA_character_,
NA_character_, NA_character_, NA_character_), se_8 = c(NA,
NA, NA, "1", NA, NA)), row.names = c(NA, 6L), class = "data.frame")
Run Code Online (Sandbox Code Playgroud)
这是我试过的代码:
# Read CSV into R
###
MyData <- read.csv(file="task.csv", header=TRUE, sep=",", stringsAsFactors = F)
# str(MyData)
# set as general option that Strings are not factors
options(stringsAsFactors = FALSE)
# save all column names
old_names1 <- colnames(MyData)
new_names1 = c("np_id","np_look_work", "np_current_work",
"hf_1", "ac_1",
"hf_2", "ac_2",
"hf_3", "ac_3",
"hf_4", "ac_4",
"hf_5", "ac_5",
"hf_6", "ac_6",
"cs_1", "se_1",
"cs_2", "se_2",
"cs_3", "se_3",
"cs_4", "se_4",
"cs_5", "se_5",
"cs_6", "se_6",
"cs_7", "se_7",
"cs_8", "se_8",
"np_before_work",
"np_keen_move",
"np_city_size",
"np_gender",
"np_age",
"np_education")
# rename columns with old_names and new_names vectors
df <- MyData %>% rename_at(vars(old_names1), ~ new_names1)
# filter rows with yes for Column look_job
# code needs dplyr::filter to ensure bas filter not used
df <- dplyr::filter(df, np_look_work == "yes")
# match all strings ending with job and replace with 1
# .*
df <- df %>%
mutate_all(funs(str_replace_all(., '.*job$', '1')))
# reorder columns
df <- df %>% select(np_id, ends_with('work'), np_before_work:np_education, starts_with('hf_'),
starts_with('ac_'), starts_with('cs_'), starts_with('se_'))
# change the blanks to NA
df <- mutate_all(df, funs(na_if(.,"")))
# change wide to long
df1 <- pivot_longer(df,
cols = -(starts_with("np_")),
names_to = c(".value", "group"),
names_sep = "_",
values_drop_na = TRUE)
Run Code Online (Sandbox Code Playgroud)
预期结果将如下所示,其中 hf_com、ac_com、curr_sal 和 exp_sal 有四列,值列分别为 hf_com_freq、ac_com_freq、curr_sal_freq 和 exp_sal_freq:
structure(list(np_id = c("81", "83", "85", "88", "1", "2"), np_look_work = c("yes",
"yes", "yes", "yes", "yes", "yes"), np_current_work = c("no", "yes",
"no", "no", "no", "no"), np_before_work = c("no", "NULL", "yes",
"yes", "yes", "yes"), np_keen_move = c("yes", "yes", "no", "no",
"no", "no"), np_city_size = c("village", "more than 500k inhabitants",
"more than 500k inhabitants", "village", "city up to 20k inhabitants",
"100k - 199k inhabitants"), np_gender = c("male", "female", "female",
"male", "female", "male"), np_age = c("18 - 24 years", "18 - 24 years",
"more than 50 years", "18 - 24 years", "31 - 40 years", "more than 50 years"
), np_education = c("secondary", "vocational", "secondary", "secondary",
"secondary", "secondary"), hf_com = c("hf1", "hf1", "hf1", "hf1",
"hf1", "hf1"), hf_com_freq = c("", "", "", "1", "1", "1"), ac_com = c("ac1",
"ac1", "ac1", "ac1", "ac1", "ac1"), ac_com_freq = c("", "", "",
"", "", "1"), curr_sal = c("cs1", "cs1", "cs1", "cs1", "cs1",
"cs1"), curr_sal_freq = c("", "", "", "", "", ""), exp_sal = c("se1",
"se1", "se1", "se1", "se1", "se1"), exp_sal_freq = c("", "",
"1", "1", "", "")), row.names = c(NA, 6L), class = "data.frame")
Run Code Online (Sandbox Code Playgroud)
实际结果是:
structure(list(np_id = c("83", "83", "85", "85", "88", "88"),
np_look_work = c("yes", "yes", "yes", "yes", "yes", "yes"
), np_current_work = c("yes", "yes", "no", "no", "no", "no"
), np_before_work = c("NULL", "NULL", "yes", "yes", "yes",
"yes"), np_keen_move = c("yes", "yes", "no", "no", "no",
"no"), np_city_size = c("more than 500k inhabitants", "more than 500k inhabitants",
"more than 500k inhabitants", "more than 500k inhabitants",
"village", "village"), np_gender = c("female", "female",
"female", "female", "male", "male"), np_age = c("18 - 24 years",
"18 - 24 years", "more than 50 years", "more than 50 years",
"18 - 24 years", "18 - 24 years"), np_education = c("vocational",
"vocational", "secondary", "secondary", "secondary", "secondary"
), group = c("2", "3", "1", "2", "1", "4"), hf = c("1", NA,
NA, "1", "1", NA), ac = c("1", NA, NA, "1", NA, NA), cs = c("1",
NA, NA, "1", NA, "1"), se = c(NA, "1", "1", NA, "1", NA)), class = c("tbl_df",
"tbl", "data.frame"), row.names = c(NA, -6L))
Run Code Online (Sandbox Code Playgroud)
我可以看到的问题是,该组列并没有告诉我,如果是hf,ac,cs或se为我所需要的。
我找到了我的问题的答案:
df3 <- df %>%
tidyr::pivot_longer(cols = c(starts_with("hf"), starts_with("ac"), starts_with("cs"), starts_with("se")),
names_to = c(".value", "level"),
names_pattern = "(.*)_(.*)"
)
Run Code Online (Sandbox Code Playgroud)