【问题标题】:New column based on row values - A better way?基于行值的新列 - 更好的方法?
【发布时间】:2018-06-07 16:17:58
【问题描述】:

肯定有更好的方法来创建与“目标”列匹配的列吗?

我在 Stack 中寻找答案,但似乎没有人需要知道如何做到这一点。也许从一个完全愚蠢的角度来看(我的头可能一直处于 Stata 模式,这是我老板的想法,他让我创建这个新的“输出”变量)。

A       <-c("bears",  "bears",     "na",   "pandas",     "pandas",    "bears",   "pandas")
B       <-c("bears",  "pandas",     "na",   "bears",     "na",          "bears",   "pandas")
target  <-c("bears", "the_zoo",   "na",   "the_zoo",  "pandas",   "bears",   "pandas")
df_test <-data.frame(A,B,target,  stringsAsFactors =FALSE)

class(df_test$B)
for(i in 1:nrow(df_test)){
                          # Case: 1: Both are equal
    df_test$output[i] <- ifelse(df_test$A[i] == df_test$B[i],
                               yes = as.character(df_test$A[i]), 
                               # Case 2: A contains NA
                                no = ifelse(df_test$A[i] == "na",
                                            yes = as.character(df_test$B[i]),
                                            # Case 2.2: B contains NA
                                            no = ifelse(df_test$B[i] =="na",
                                                        yes = as.character(df_test$A[i]),
                                                        # Case 3: All other possibilities are "the_zoo"
                                                        no = "the_zoo"
                                                        )))
                                                    }
df_test



> df_test
       A      B  target  output
1  bears  bears   bears   bears
2  bears pandas the_zoo the_zoo
3     na     na      na      na
4 pandas  bears the_zoo the_zoo
5 pandas     na  pandas  pandas
6  bears  bears   bears   bears
7 pandas pandas  pandas  pandas

【问题讨论】:

    标签: r if-statement dataframe


    【解决方案1】:

    有什么问题

    A       <-c("bears",  "bears",     "na",   "pandas",     "pandas",    "bears",   "pandas")
    B       <-c("bears",  "pandas",     "na",   "bears",     "na",          "bears",   "pandas")
    target  <-c("bears", "the_zoo",   "na",   "the_zoo",  "pandas",   "bears",   "pandas")
    df_test <-data.frame(A,B,target,  stringsAsFactors =FALSE)
    
    df_test$test <- with(df_test, ifelse(A == B, A, 
                           ifelse(A == "na",B, 
                                  ifelse(B == "na", A, "the_zoo"))))
    
    
    print(df_test)
    

    产生:

           A      B  target    test
    1  bears  bears   bears   bears
    2  bears pandas the_zoo the_zoo
    3     na     na      na      na
    4 pandas  bears the_zoo the_zoo
    5 pandas     na  pandas  pandas
    6  bears  bears   bears   bears
    7 pandas pandas  pandas  pandas
    

    您不需要 for 循环,因为 ifelse 已经矢量化。

    【讨论】:

    • 您的代码无法正常工作,因为他的 NA 是字符,请查看您的第 5ª 行。
    • @JuanAntonioRoldánDíaz 刚刚改了
    • 我真的认为我尝试过这个,但显然我在某个地方犯了错误。但大概你需要在 As 和 Bs 之前的 $ 运算符?
    • @SeánMcK 对此感到抱歉。我添加了 a ,你可以把它包裹起来,然后你就不需要 $
    【解决方案2】:

    这里清理代码的一个选项是使用dplyr 包中的case_when

    library(dplyr)
    
    df_test$output <-
    case_when(
        df_test$A == df_test$B ~ as.character(df_test$A),
        df_test$A == "na" ~ as.character(df_test$B),
        df_test$B =="na" ~ as.character(df_test$A),
        TRUE ~ "the_zoo"
    )
    

    请注意,如果 AB 列已经是字符类型,正如您的代码的一部分似乎假设的那样,那么您可以删除上面对 as.character 的不必要调用。

    【讨论】:

    • 也喜欢 dplyr 解决方案——我真的应该考虑这个。一般来说,你对 case_when 什么时候应该使用 vs ifelse 有什么想法吗?
    • @SeánMcK 这实际上是代码可读性和可维护性的问题。您接受的答案中的代码难以阅读,并且相对难以维护。从性能的角度来看,我认为任何一个答案都很好。
    猜你喜欢
    • 2020-03-22
    • 2023-02-09
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-07-14
    • 1970-01-01
    • 2022-08-11
    相关资源
    最近更新 更多