如何创建一个函数来创建一个包含组合观察值的列
How to make a function that creates a column with combined observations
我显然是数据清理的新手,而且我在清理调查导出时遇到了问题。这是我的数据框在原始形式下的样子。
Var1 Colname1 Colname2 Colname3 Var2
Observation1 NA NA Val1 Val_1
Observation2 NA Val2 NA Val_1
Observation3 Val3 NA NA Val_1
Observation4 Val4 Val5 NA Val_2
Observation5 NA NA Val6 Val_2
我希望将我的数据清理成如下所示:
Var1 SubVar1 Var2
Observation1 Val1 Val_1
Observation2 Val2 Val_1
Observation3 Val3 Val_1
Observation4 Val4 Val_2
Observation4 Val5 Val_2
Observation5 Val6 Val_2
我已尝试删除 NA 值:
df1 <- na.omit(c(Colname1, Colname2, Colname3))
问题是它会删除所有行,因为每一行都有一个 NA。我还尝试连接这些值,然后使用 separate_rows() 函数,但这只适用于一列中只有一个值的观察结果。对于在多个列中包含值的观察(请参阅观察 4),这将不起作用。
感谢你们提供的任何帮助!
试试,
data %>% mutate(SubVar1 = coalesce(Colname1,Colname2,Colname3)) %>%
select(Var1, SubVar1, Var2)
我会认为这是从宽到长的枢轴(重塑)操作:
library(dplyr)
library(tidyr)
data %>%
pivot_longer(cols = Colname1:Colname3, values_to = "SubVar1") %>%
filter(!is.na(SubVar1)) %>%
select(Var1, SubVar1, Var2)
# # A tibble: 6 × 3
# Var1 SubVar1 Var2
# <chr> <chr> <chr>
# 1 Observation1 Val1 Val_1
# 2 Observation2 Val2 Val_1
# 3 Observation3 Val3 Val_1
# 4 Observation4 Val4 Val_2
# 5 Observation4 Val5 Val_2
# 6 Observation5 Val6 Val_2
要了解发生了什么,运行 第一行,然后是第一行和第二行,然后是第一行、第二行和第三行,等等。请参阅 ?pivot_longer
以了解其他几个选项以指定哪个要转换的列 - 您可以明确命名,使用 names_pattern = "Colname"
之类的名称模式,或者像我上面那样使用 Colname1:Colname3
到 select 连续列。
我们可以通过 row/column 索引以矢量化方式使用 base R
。对列名为'Colname'的列进行子集化,然后用max.col
、cbind
行序列得到每一行的非NA元素的列索引,提取对应的元素并创建新 data.frame
i1 <- startsWith(names(df1), "Colname")
data.frame(df1['Var1'], SubVar1 = df1[i1][cbind(seq_len(nrow(df1)),
max.col(!is.na(df1[i1]), "first"))], df1['Var2'])
Var1 SubVar1 Var2
1 Observation1 Val1 Val_1
2 Observation2 Val2 Val_1
3 Observation3 Val3 Val_1
4 Observation4 Val4 Val_2
5 Observation5 Val6 Val_2
数据
df1 <- structure(list(Var1 = c("Observation1", "Observation2", "Observation3",
"Observation4", "Observation5"), Colname1 = c(NA, NA, "Val3",
"Val4", NA), Colname2 = c(NA, "Val2", NA, "Val5", NA), Colname3 = c("Val1",
NA, NA, NA, "Val6"), Var2 = c("Val_1", "Val_1", "Val_1", "Val_2",
"Val_2")), class = "data.frame", row.names = c(NA, -5L))
我显然是数据清理的新手,而且我在清理调查导出时遇到了问题。这是我的数据框在原始形式下的样子。
Var1 Colname1 Colname2 Colname3 Var2
Observation1 NA NA Val1 Val_1
Observation2 NA Val2 NA Val_1
Observation3 Val3 NA NA Val_1
Observation4 Val4 Val5 NA Val_2
Observation5 NA NA Val6 Val_2
我希望将我的数据清理成如下所示:
Var1 SubVar1 Var2
Observation1 Val1 Val_1
Observation2 Val2 Val_1
Observation3 Val3 Val_1
Observation4 Val4 Val_2
Observation4 Val5 Val_2
Observation5 Val6 Val_2
我已尝试删除 NA 值:
df1 <- na.omit(c(Colname1, Colname2, Colname3))
问题是它会删除所有行,因为每一行都有一个 NA。我还尝试连接这些值,然后使用 separate_rows() 函数,但这只适用于一列中只有一个值的观察结果。对于在多个列中包含值的观察(请参阅观察 4),这将不起作用。
感谢你们提供的任何帮助!
试试,
data %>% mutate(SubVar1 = coalesce(Colname1,Colname2,Colname3)) %>%
select(Var1, SubVar1, Var2)
我会认为这是从宽到长的枢轴(重塑)操作:
library(dplyr)
library(tidyr)
data %>%
pivot_longer(cols = Colname1:Colname3, values_to = "SubVar1") %>%
filter(!is.na(SubVar1)) %>%
select(Var1, SubVar1, Var2)
# # A tibble: 6 × 3
# Var1 SubVar1 Var2
# <chr> <chr> <chr>
# 1 Observation1 Val1 Val_1
# 2 Observation2 Val2 Val_1
# 3 Observation3 Val3 Val_1
# 4 Observation4 Val4 Val_2
# 5 Observation4 Val5 Val_2
# 6 Observation5 Val6 Val_2
要了解发生了什么,运行 第一行,然后是第一行和第二行,然后是第一行、第二行和第三行,等等。请参阅 ?pivot_longer
以了解其他几个选项以指定哪个要转换的列 - 您可以明确命名,使用 names_pattern = "Colname"
之类的名称模式,或者像我上面那样使用 Colname1:Colname3
到 select 连续列。
我们可以通过 row/column 索引以矢量化方式使用 base R
。对列名为'Colname'的列进行子集化,然后用max.col
、cbind
行序列得到每一行的非NA元素的列索引,提取对应的元素并创建新 data.frame
i1 <- startsWith(names(df1), "Colname")
data.frame(df1['Var1'], SubVar1 = df1[i1][cbind(seq_len(nrow(df1)),
max.col(!is.na(df1[i1]), "first"))], df1['Var2'])
Var1 SubVar1 Var2
1 Observation1 Val1 Val_1
2 Observation2 Val2 Val_1
3 Observation3 Val3 Val_1
4 Observation4 Val4 Val_2
5 Observation5 Val6 Val_2
数据
df1 <- structure(list(Var1 = c("Observation1", "Observation2", "Observation3",
"Observation4", "Observation5"), Colname1 = c(NA, NA, "Val3",
"Val4", NA), Colname2 = c(NA, "Val2", NA, "Val5", NA), Colname3 = c("Val1",
NA, NA, NA, "Val6"), Var2 = c("Val_1", "Val_1", "Val_1", "Val_2",
"Val_2")), class = "data.frame", row.names = c(NA, -5L))