我想根据这些列中的所有值是否满足条件来重命名数据中的列。例如,在数字列中,如果所有值都大于 5,则将该列重命名为 large_values
,否则保持列名不变。另一个示例,如果字符列中的所有值都没有 &
字符,则将该列重命名为 no_ampersand
。
library(tibble)
df <-
tribble(~age_1, ~age_2, ~string_1,
2, 7, "abc",
3, 8, "efg",
1, 11, "hi&",
10, 6, "klmn",
50, 100, "opq")
is_larger_than_val <- function(x, y) {
all(x > y)
}
&
?does_contain_ampersand <- function(x) {
all(grepl("&", x))
}
因此,使用这些函数,我如何重命名 df
的标题,以便何时
is_larger_than_val(df$age_2, 5)
[1] TRUE
将 age_2
重命名为 large_values
,但在其他情况下
is_larger_than_val(df$age_1, 5)
[1] FALSE
会保持 age_1
不变吗?
同样,因为
does_contain_ampersand(df$string_1)
[1] FALSE
会保持 string_1
不变(但如果它是 TRUE
,那么 string_1
会被重命名为 no_ampersand
)?
给定当前数据,根据我在 is_larger_than_val()
和 does_contain_ampersand()
中指定的条件重命名应该返回:
# A tibble: 5 x 3
age_1 large_values string_1
<dbl> <dbl> <chr>
1 2 7 abc
2 3 8 efg
3 1 11 hi&
4 10 6 klmn
5 50 100 opq
我确信这可以通过嵌套一些 if else
语句来实现,但我想知道是否有更简单的方法(也许使用 tidyverse
技巧?)。
谢谢!
R
文件的 JSON
数据对象。一旦我将 JSON
文件读入 R
,它最终会变成以下格式:vec <- c(1, 2, 3)
names(vec) <- c("A", "B", "C")
my_data_object_as_list <- as.list(vec)
my_data_object_as_list
## $A
## [1] 1
## $B
## [1] 2
## $C
## [1] 3
my_data_object_as_list
并将其重组为表格。require(tidyr)
require(dplyr)
require(tidyselect)
organize_in_table <- function(as_list_object) {
as_list_object %>%
bind_rows() %>%
pivot_longer(cols = tidyselect::everything())
}
organize_in_table(my_data_object_as_list)
## # A tibble: 3 x 2
## name value
## <chr> <dbl>
## 1 A 1
## 2 B 2
## 3 C 3
organize_in_table()
非常通用,所以它返回一个表,其中的列名(name
和 value
)并不表示每列的含义。为了解决这个问题,我想给 purpose
添加一个 organize_in_table()
参数,下面是一个例子:organize_in_table <-
function(as_list_object,
purpose = NULL) {
table <- as_list_object %>%
bind_rows() %>%
pivot_longer(cols = tidyselect::everything())
if (is.null(purpose)) {
return(table)
} else if (purpose == "match_letters_and_numbers") {
table <- rename(table, letters = name, numbers = value)
}
return(table)
}
现在,organize_in_table()
可以返回具有有意义名称的对象:
df_letters_and_numbers <-
organize_in_table(my_data_object_as_list, "match_letters_and_numbers")
> df_letters_and_numbers
## # A tibble: 3 x 2
## letters numbers
## <chr> <dbl>
## 1 A 1
## 2 B 2
## 3 C 3
df_letters_and_numbers[1]
被正确命名为 letters
而 df_letters_and_numbers[2]
是 numbers
?我在什么基础上验证过——当我在 table
中重命名 organize_in_table()
时——第一列 (name
) 都是字母,第二列 (value
) 都是数字?我没有验证。如果 my_data_object_as_list
看起来像这样会怎样:
vec_2 <- c("A", "B", "C")
names(vec_2) <- c(1, 2, 3)
my_data_object_as_list_2 <- as.list(vec_2)
> my_data_object_as_list_2
## $`1`
## [1] "A"
## $`2`
## [1] "B"
## $`3`
## [1] "C"
然后,如果我运行 organize_in_table(my_data_object_as_list_2, "match_letters_and_numbers")
,我将获得列名不匹配的数据框:
## # A tibble: 3 x 2
## letters numbers
## <chr> <chr>
## 1 1 A
## 2 2 B
## 3 3 C
所以我的结论是,我必须根据要重命名的每一列的内容,在 organize_in_table()
内调整重命名步骤。为此,我认为第一步应该是为我想要执行的每个测试定义一个单独的函数(例如,列号中的所有值都是吗?所有值都是字母吗?)。因为我想让 organize_in_table()
尽可能地可扩展,所以我希望它接受我可以为其构建测试功能的任何测试。
答案 0 :(得分:2)
在数据上使用 sapply
以在列上创建逻辑索引,但要注意与号大小写中的字符列:
i <- sapply(df, is_larger_than_val, y = 5)
names(df)[i] <- "large_values"
i <- sapply(df, does_contain_ampersand)
i <- i | !sapply(df, is.character)
names(df)[!i] <- "no_ampersand"
names(df)
#[1] "age_1" "large_values" "no_ampersand"
答案 1 :(得分:2)
sls deploy
解决方案非常简单,非常棒。这是一个带有 sapply
的替代解决方案,需要更多的努力。我认为它的原理相同,但我添加了一个步骤来识别数字和字符串列,以确保仅测试某些列
data.table