Using strsplit within dplyr::mutate (without tibble::data_frame) raises "Evaluation error: non-character argument"
Using strsplit within dplyr::mutate (without tibble::data_frame) raises "Evaluation error: non-character argument"
编辑: 我的 df
创建有错字,MediaName
的最后一个值缺少 _
;现在已更正。
我想根据第三个变量 Phase
的值在数据框中创建一个新变量 TrialId
作为另一个变量 MediaName
值的一部分我可以在 dplyr::mutate
中使用 strsplit
和 ifelse
来做到这一点,如下所示:
library(dplyr)
# Creating a simple data frame for the example
df <- data.frame(Phase = c(rep("Familiarisation",8),rep("Test",3)),
MediaName = c("Flip_A1_G1","Reg_B2_S1","Reg_A2_G1","Flip_B1_S1",
"Reg_A1_G2","Flip_B2_S2","Reg_A2_G2","Flip_B1_S2",
"HC_A1L","TC_B1R","RC_BL_2R"))
# Creating a new column
df <- df %>%
mutate(TrialId = ifelse(Phase == "Familiarisation",
sapply(strsplit(MediaName, "_"), "[", 2),
sapply(strsplit(MediaName, "_"), "[", 1)))
预期结果是
> df$TrialId
[1] "A1" "B2" "A2" "B1" "A1" "B2" "A2" "B1" "HC" "TC" "RC"
但是这给了我以下错误,因为我相信 strsplit
:
Error in mutate_impl(.data, dots) :
Evaluation error: non-character argument.
我从 了解到,在这个小示例中,我可以通过将我的数据框定义为 tibble::data_frame
来轻松解决我的问题,而不知道为什么这样可以解决问题。我不能完全做到这一点,因为在我的实际代码中 df
来自读取 csv 文件(使用 read.csv()
)。我一直认为使用 df <- df %>% as_tibble() %>% mutate(...)
会以类似的方式解决问题,但事实并非如此(为什么?)。
有没有办法在读取文件时实际使用 tibble
?或者是否有另一种方法可以实现我需要做的事情,而不用 strsplit
也许?
我还在 this other SO question 上读到,您可以使用 tidyr::separate
,但它并没有完全按照我的要求执行,因为我需要根据值保留第一个或第二个值Phase
.
您遇到的问题是因为字符串在factor
中被自动转换,所以您不能将strsplit()
应用于非字符串对象。我的解决方案只是将 MediaName
转换为 string
类型。
require(dplyr)
df <- df %>%
dplyr::mutate(MediaName = as.character(levels(df$MediaName))[df$MediaName]) %>%
dplyr::mutate(TrialId = ifelse(Phase == "Familiarisation",
sapply(strsplit(MediaName, "_"), "[", 2),
sapply(strsplit(MediaName, "_"), "[", 1)))
solution<- c("A1", "B2", "A2", "B1", "A1", "B2", "A2", "B1", "HC", "TC", "RC")
identical(solution, df$TrialId)
[1] TRUE
你可以试试:
library(tidyverse)
# your first data
df_old <- data.frame(Phase = c(rep("Familiarisation",8),rep("Test",3)),
MediaName = c("Flip_A1_G1","Reg_B2_S1","Reg_A2_G1","Flip_B1_S1",
"Reg_A1_G2","Flip_B2_S2","Reg_A2_G2","Flip_B1_S2",
"HC_A1L","TC_B1R","RC_BL2R"))
df_old %>%
separate(MediaName, into=letters[1:3], sep="_", fill = "left", remove = FALSE) %>%
select(Phase, MediaName, TrialId=b)
Phase MediaName TrialId
1 Familiarisation Flip_A1_G1 A1
2 Familiarisation Reg_B2_S1 B2
3 Familiarisation Reg_A2_G1 A2
4 Familiarisation Flip_B1_S1 B1
5 Familiarisation Reg_A1_G2 A1
6 Familiarisation Flip_B2_S2 B2
7 Familiarisation Reg_A2_G2 A2
8 Familiarisation Flip_B1_S2 B1
9 Test HC_A1L HC
10 Test TC_B1R TC
11 Test RC_BL2R RC
这是根据提供的示例数据的硬编码解决方案。用"_"
隔开,如果只有两个而不是三个"_"
从左边填NA
。最后,select 您需要的列。
编辑
对于您的新数据,情况会稍微复杂一些。但你可以试试:
df %>%
add_column(MediaName_keep=df$MediaName) %>%
group_by(MediaName_keep) %>%
separate_rows(MediaName, sep="_") %>%
mutate(n=1:n()) %>%
filter((Phase == "Familiarisation" & n == 2) | (Phase == "Test" & n == 1)) %>%
select(Phase, MediaName=MediaName_keep, TrialId=MediaName)
# A tibble: 11 x 3
# Groups: MediaName [11]
Phase MediaName TrialId
<fctr> <fctr> <chr>
1 Familiarisation Flip_A1_G1 A1
2 Familiarisation Reg_B2_S1 B2
3 Familiarisation Reg_A2_G1 A2
4 Familiarisation Flip_B1_S1 B1
5 Familiarisation Reg_A1_G2 A1
6 Familiarisation Flip_B2_S2 B2
7 Familiarisation Reg_A2_G2 A2
8 Familiarisation Flip_B1_S2 B1
9 Test HC_A1L HC
10 Test TC_B1R TC
11 Test RC_BL_2R RC
思路是一样的。分开,但此时按 MediaName_keep
添加并计算新行,然后根据您的需要进行过滤。
编辑: 我的 df
创建有错字,MediaName
的最后一个值缺少 _
;现在已更正。
我想根据第三个变量 Phase
的值在数据框中创建一个新变量 TrialId
作为另一个变量 MediaName
值的一部分我可以在 dplyr::mutate
中使用 strsplit
和 ifelse
来做到这一点,如下所示:
library(dplyr)
# Creating a simple data frame for the example
df <- data.frame(Phase = c(rep("Familiarisation",8),rep("Test",3)),
MediaName = c("Flip_A1_G1","Reg_B2_S1","Reg_A2_G1","Flip_B1_S1",
"Reg_A1_G2","Flip_B2_S2","Reg_A2_G2","Flip_B1_S2",
"HC_A1L","TC_B1R","RC_BL_2R"))
# Creating a new column
df <- df %>%
mutate(TrialId = ifelse(Phase == "Familiarisation",
sapply(strsplit(MediaName, "_"), "[", 2),
sapply(strsplit(MediaName, "_"), "[", 1)))
预期结果是
> df$TrialId
[1] "A1" "B2" "A2" "B1" "A1" "B2" "A2" "B1" "HC" "TC" "RC"
但是这给了我以下错误,因为我相信 strsplit
:
Error in mutate_impl(.data, dots) :
Evaluation error: non-character argument.
我从 tibble::data_frame
来轻松解决我的问题,而不知道为什么这样可以解决问题。我不能完全做到这一点,因为在我的实际代码中 df
来自读取 csv 文件(使用 read.csv()
)。我一直认为使用 df <- df %>% as_tibble() %>% mutate(...)
会以类似的方式解决问题,但事实并非如此(为什么?)。
有没有办法在读取文件时实际使用 tibble
?或者是否有另一种方法可以实现我需要做的事情,而不用 strsplit
也许?
我还在 this other SO question 上读到,您可以使用 tidyr::separate
,但它并没有完全按照我的要求执行,因为我需要根据值保留第一个或第二个值Phase
.
您遇到的问题是因为字符串在factor
中被自动转换,所以您不能将strsplit()
应用于非字符串对象。我的解决方案只是将 MediaName
转换为 string
类型。
require(dplyr)
df <- df %>%
dplyr::mutate(MediaName = as.character(levels(df$MediaName))[df$MediaName]) %>%
dplyr::mutate(TrialId = ifelse(Phase == "Familiarisation",
sapply(strsplit(MediaName, "_"), "[", 2),
sapply(strsplit(MediaName, "_"), "[", 1)))
solution<- c("A1", "B2", "A2", "B1", "A1", "B2", "A2", "B1", "HC", "TC", "RC")
identical(solution, df$TrialId)
[1] TRUE
你可以试试:
library(tidyverse)
# your first data
df_old <- data.frame(Phase = c(rep("Familiarisation",8),rep("Test",3)),
MediaName = c("Flip_A1_G1","Reg_B2_S1","Reg_A2_G1","Flip_B1_S1",
"Reg_A1_G2","Flip_B2_S2","Reg_A2_G2","Flip_B1_S2",
"HC_A1L","TC_B1R","RC_BL2R"))
df_old %>%
separate(MediaName, into=letters[1:3], sep="_", fill = "left", remove = FALSE) %>%
select(Phase, MediaName, TrialId=b)
Phase MediaName TrialId
1 Familiarisation Flip_A1_G1 A1
2 Familiarisation Reg_B2_S1 B2
3 Familiarisation Reg_A2_G1 A2
4 Familiarisation Flip_B1_S1 B1
5 Familiarisation Reg_A1_G2 A1
6 Familiarisation Flip_B2_S2 B2
7 Familiarisation Reg_A2_G2 A2
8 Familiarisation Flip_B1_S2 B1
9 Test HC_A1L HC
10 Test TC_B1R TC
11 Test RC_BL2R RC
这是根据提供的示例数据的硬编码解决方案。用"_"
隔开,如果只有两个而不是三个"_"
从左边填NA
。最后,select 您需要的列。
编辑
对于您的新数据,情况会稍微复杂一些。但你可以试试:
df %>%
add_column(MediaName_keep=df$MediaName) %>%
group_by(MediaName_keep) %>%
separate_rows(MediaName, sep="_") %>%
mutate(n=1:n()) %>%
filter((Phase == "Familiarisation" & n == 2) | (Phase == "Test" & n == 1)) %>%
select(Phase, MediaName=MediaName_keep, TrialId=MediaName)
# A tibble: 11 x 3
# Groups: MediaName [11]
Phase MediaName TrialId
<fctr> <fctr> <chr>
1 Familiarisation Flip_A1_G1 A1
2 Familiarisation Reg_B2_S1 B2
3 Familiarisation Reg_A2_G1 A2
4 Familiarisation Flip_B1_S1 B1
5 Familiarisation Reg_A1_G2 A1
6 Familiarisation Flip_B2_S2 B2
7 Familiarisation Reg_A2_G2 A2
8 Familiarisation Flip_B1_S2 B1
9 Test HC_A1L HC
10 Test TC_B1R TC
11 Test RC_BL_2R RC
思路是一样的。分开,但此时按 MediaName_keep
添加并计算新行,然后根据您的需要进行过滤。