如何通过管道传输到 R 中的 if 语句
How to pipe to if statements in R
我有来自我的 Facebook、Twitter、Instagram、Youtube 和 LinkedIn 帐户的数据,我想对其进行分析。我有一个类似于以下的数据框:
df <- data.frame(tw_likes = c(5,4,6,NA,NA,NA,NA,NA,NA),
tw_comments = c(3,5,NA,NA,NA,NA,NA,NA,NA),
fb_likes = c(NA,NA,NA,7,4,8,NA,NA,NA),
fb_comments = c(NA,NA,NA,NA,NA,7,NA,NA,NA),
ig_likes = c(NA,NA,NA,NA,NA,NA,NA,NA,5),
ig_comments = c(NA,NA,NA,NA,NA,NA,43,4,2))
我想做的是创建一个额外的列 Platform
,它将采用 "Twitter, "Facebook 的值,或基于上述数据框的 "Instagram"。
我的策略如下:
for(i in 1:nrow(df){
if(!is.na(df$tw_likes[i]) | !is.na(df$tw_comments[i])){
df$Platform[i] <- "Twitter"
}
else if(!is.na(df$fb_likes[i]) | !is.na(df$fb_comments[i])){
df$Platform[i] <- "Facebook"
}
else if(!is.na(df$ig_likes[i]) | !is.na(df$ig_comments[i])){
df$Platform[i] <- "Instagram"
}
}
这确实有效,但读起来更乱了。实际上,我有更多的专栏和更多的社交媒体平台需要处理,那么有没有办法通过管道传输数据,这样我至少不必写这么多次 df$
?
我的另一个想法是,如果我不能删除 df$
,我可以将 !is.na()
语句合并为每个 if 语句的一个语句吗?
这是 dplyr
的 case_when()
的选项
df %>%
mutate(Plataform = case_when(
!is.na(tw_likes) | !is.na(tw_comments) ~ "Twitter",
!is.na(fb_likes) | !is.na(fb_comments) ~ "Facebook",
!is.na(ig_likes) | !is.na(ig_comments) ~ "Instagram"))
这是 base R
中将数据集拆分为具有相同前缀列的 list
的一种方法(通过从列名称中删除后缀子字符串),执行 rowSums
以创建一个逻辑 matrix
,应用 max.col
来获取每一行的列位置,并通过按照拆分列名称的相同顺序传递替换值向量来更改该索引
i1 <- max.col(sapply(split.default(df, sub("_.*", "", names(df))),
function(x) rowSums(!is.na(x)) > 0 ), 'first')
df$Platform <- c("Facebook", "Instagram", "Twitter")[i1]
df$Platform
#[1] "Twitter" "Twitter" "Twitter" "Facebook" "Facebook"
#[6] "Facebook" "Instagram" "Instagram" "Instagram"
这是另一种方法,使用 dplyr
和 tidyr
将数据拉成长格式,过滤掉空白,并根据查找 table 添加更长的名称:
library(tidyr); library(dplyr)
df %>%
pivot_longer(cols = everything(),
names_to = c("pltfm", "stat"),
names_sep = "_",
values_to = "value") %>%
filter(!is.na(value)) %>%
left_join(
tibble(pltfm = c("tw", "fb", "ig"),
Platform = c("Twitter", "Facebook", "Instagram"))
)
#Joining, by = "pltfm"
## A tibble: 13 x 4
# pltfm stat value Platform
# <chr> <chr> <dbl> <chr>
# 1 tw likes 5 Twitter
# 2 tw comments 3 Twitter
# 3 tw likes 4 Twitter
# 4 tw comments 5 Twitter
# 5 tw likes 6 Twitter
# 6 fb likes 7 Facebook
# 7 fb likes 4 Facebook
# 8 fb likes 8 Facebook
# 9 fb comments 7 Facebook
#10 ig comments 43 Instagram
#11 ig comments 4 Instagram
#12 ig likes 5 Instagram
#13 ig comments 2 Instagram
我有来自我的 Facebook、Twitter、Instagram、Youtube 和 LinkedIn 帐户的数据,我想对其进行分析。我有一个类似于以下的数据框:
df <- data.frame(tw_likes = c(5,4,6,NA,NA,NA,NA,NA,NA),
tw_comments = c(3,5,NA,NA,NA,NA,NA,NA,NA),
fb_likes = c(NA,NA,NA,7,4,8,NA,NA,NA),
fb_comments = c(NA,NA,NA,NA,NA,7,NA,NA,NA),
ig_likes = c(NA,NA,NA,NA,NA,NA,NA,NA,5),
ig_comments = c(NA,NA,NA,NA,NA,NA,43,4,2))
我想做的是创建一个额外的列 Platform
,它将采用 "Twitter, "Facebook 的值,或基于上述数据框的 "Instagram"。
我的策略如下:
for(i in 1:nrow(df){
if(!is.na(df$tw_likes[i]) | !is.na(df$tw_comments[i])){
df$Platform[i] <- "Twitter"
}
else if(!is.na(df$fb_likes[i]) | !is.na(df$fb_comments[i])){
df$Platform[i] <- "Facebook"
}
else if(!is.na(df$ig_likes[i]) | !is.na(df$ig_comments[i])){
df$Platform[i] <- "Instagram"
}
}
这确实有效,但读起来更乱了。实际上,我有更多的专栏和更多的社交媒体平台需要处理,那么有没有办法通过管道传输数据,这样我至少不必写这么多次 df$
?
我的另一个想法是,如果我不能删除 df$
,我可以将 !is.na()
语句合并为每个 if 语句的一个语句吗?
这是 dplyr
的 case_when()
df %>%
mutate(Plataform = case_when(
!is.na(tw_likes) | !is.na(tw_comments) ~ "Twitter",
!is.na(fb_likes) | !is.na(fb_comments) ~ "Facebook",
!is.na(ig_likes) | !is.na(ig_comments) ~ "Instagram"))
这是 base R
中将数据集拆分为具有相同前缀列的 list
的一种方法(通过从列名称中删除后缀子字符串),执行 rowSums
以创建一个逻辑 matrix
,应用 max.col
来获取每一行的列位置,并通过按照拆分列名称的相同顺序传递替换值向量来更改该索引
i1 <- max.col(sapply(split.default(df, sub("_.*", "", names(df))),
function(x) rowSums(!is.na(x)) > 0 ), 'first')
df$Platform <- c("Facebook", "Instagram", "Twitter")[i1]
df$Platform
#[1] "Twitter" "Twitter" "Twitter" "Facebook" "Facebook"
#[6] "Facebook" "Instagram" "Instagram" "Instagram"
这是另一种方法,使用 dplyr
和 tidyr
将数据拉成长格式,过滤掉空白,并根据查找 table 添加更长的名称:
library(tidyr); library(dplyr)
df %>%
pivot_longer(cols = everything(),
names_to = c("pltfm", "stat"),
names_sep = "_",
values_to = "value") %>%
filter(!is.na(value)) %>%
left_join(
tibble(pltfm = c("tw", "fb", "ig"),
Platform = c("Twitter", "Facebook", "Instagram"))
)
#Joining, by = "pltfm"
## A tibble: 13 x 4
# pltfm stat value Platform
# <chr> <chr> <dbl> <chr>
# 1 tw likes 5 Twitter
# 2 tw comments 3 Twitter
# 3 tw likes 4 Twitter
# 4 tw comments 5 Twitter
# 5 tw likes 6 Twitter
# 6 fb likes 7 Facebook
# 7 fb likes 4 Facebook
# 8 fb likes 8 Facebook
# 9 fb comments 7 Facebook
#10 ig comments 43 Instagram
#11 ig comments 4 Instagram
#12 ig likes 5 Instagram
#13 ig comments 2 Instagram