r - 如何编写 R 函数以根据两个现有列的条件值在任何数据框中创建新列?
问题描述
问题:
我有一个相当令人沮丧的问题。我正在尝试编写一个函数,该函数将根据该数据帧的两个现有列中的值在任何给定数据帧中创建/填充一个新列。
语境:
我经常使用引用具有两个维度(项目 ID (1-7) 和 localeID(de_DE、fr_FR、jp_JP 等)的事件的数据库。
projectId localeId
1 jp_JP
2 es_ES
3 de_DE
1 jp_JP
2 es_ES
3 de_DE
我必须从数据库执行 ETL 并创建一个基于 projectId 和 localeID 的新“市场”维度。例如,projectId 为 1 和 localeId 为 jp_JP 可能意味着市场是“JAPAN1”。
projectId localeId market
1 jp_JP JAPAN1
2 es_ES SPAIN2
3 au_AU AUS3
4 us_US US4
5 en_EN ENGLAND5
6 de_DE GERMANY6
当前成功代码:
现在写,我有一段冗长的使用 ifelse 函数的 R 代码。IE...
df$market <- ifelse(df$localeId == "jp_JP" & df$projectId == '1', "JAPAN1")
df$market <- ifelse(df$localeId == "es_ES" & df$projectId == '10', "SPAIN10")
这可以。它完成了工作。不幸的是,我有很多处理这个市场功能的脚本,我不想一遍又一遍地复制粘贴这个 ifelse 代码。相反,我想编写一个可用于任何数据框的函数,以根据 localeId 和 projectId 创建一个新的市场列。
尝试/失败的解决方案:
market_names <- function(df, "market", "projectId", "localeId"){
df$market <- NA
x <- ifelse(projectId == 1, "1",
ifelse(projectId == 2, "2", projectId)
y <- ifelse(localeId == "jp_JP", "JAPAN",
ifelse(localeId == "es_ES", "SPAIN", localeId)
for(i in 1:nrow(df)){
df[i,]$market <- paste(x,y, sep = "")
}
df <- market_names(df, "market", "projectId", "localeId")
不幸的是,当我尝试将数据帧传递给函数时,代码就崩溃了,甚至不会运行。
要求:
我希望这里有人遇到过类似的问题,并且可以就如何修复此功能提供建议,以便它可以随时用于任何数据帧。我的 projectId 和 localeId 的维度总是相同的,所以我认为这会在将来为我节省很多时间。
如果您认为有一种更简单的方法可以在没有功能的情况下完成所有这些操作,我也很想听听您的想法!
提前致谢!
解决方案
由于多种原因,您的功能不起作用。例如,您缺少ifelse
s 上的右括号。函数定义上的右大括号也丢失了。for 循环中的x
andy
变量是长度 > 1 的向量,因此它们也需要索引。参数不应该是单独的字符串,它们应该分配给可以在函数中引用的变量。您的嵌套ifelse
s 仅处理两种情况:1 和 2,以及 JAPAN 和 SPAIN。最后,您的函数不返回任何内容。修复这些东西后,你最终会得到这个:
market_names <- function(df){
df$market <- NA
x <- ifelse(df$projectId == 1, "1",
ifelse(df$projectId == 2, "2", df$projectId))
y <- ifelse(df$localeId == "jp_JP", "JAPAN",
ifelse(df$localeId == "es_ES", "SPAIN", df$localeId))
for(i in 1:nrow(df)){
df[i,]$market <- paste(x[i],y[i], sep = "")
}
df
}
market_names(df)
#### OUTPUT ####
# A tibble: 6 x 3
projectId localeId market
<dbl> <chr> <chr>
1 1 jp_JP 1JAPAN
2 2 es_ES 2SPAIN
3 3 au_AU 3au_AU
4 4 us_US 4us_US
5 5 en_EN 5en_EN
6 6 de_DE 6de_DE
很明显x
应该在为什么y
在之后paste
。您的条件还需要更好地处理所有情况。
只使用映射到国家名称的国家代码列表可能是最简单的。然后可以将该列localeId
用作索引。循环和条件都不是必需的:
# Country proper names can be accessed using codes.
country_codes <- list("jp_JP" = "JAPAN",
"es_ES" = "SPAIN",
"de_DE" = "GERMANY",
"au_AU" = "AUS",
"us_US" = "US",
"en_EN" = "ENGLAND",
"de_DE" = "GERMANY"
)
# Pass in dataframe and country codes.
market_names <- function(df, country_codes){
df$market <- paste0(unlist(country_codes[df$localeId], use.names = F),
df$projectId
)
df
}
# Function call:
market_names(df, country_codes)
#### OUTPUT ####
# A tibble: 6 x 3
projectId localeId market
<dbl> <chr> <chr>
1 1 jp_JP JAPAN1
2 2 es_ES SPAIN2
3 3 au_AU AUS3
4 4 us_US US4
5 5 en_EN ENGLAND5
6 6 de_DE GERMANY6
推荐阅读
- javascript - 在 Material-UI TableCell 中格式化日期字符串
- php - 将 MYSQL 数据表从网站导出到 CSV 时出现错误字符
- ios - IBOutlet:在隐式展开可选值时意外发现 nil
- xslt - xml to xml transformation - trying to merge two XSLs
- opencv - OpenCV(3.4.3) !_src.empty() in function 'cvtColor' 错误
- python - 使用 Elasticsearch DSL Python 的复合 Elasticsearch 聚合
- json - 在 PhpStorm 内置 Web 服务器中打开 JSON 文件
- django - 在正在进行的项目中更改管理主题
- suitecrm - SuiteCRM api v8 没有给出任何响应
- angularjs - AngularJS 与同一浏览器中的两个选项卡进行通信