【问题标题】:How do I create a new column based on multiple conditions from multiple columns?如何根据来自多个列的多个条件创建新列?
【发布时间】:2017-01-17 06:05:11
【问题描述】:

我正在尝试根据其他列的几个条件向数据框中添加一个新列。我有以下数据:

> commute <- c("walk", "bike", "subway", "drive", "ferry", "walk", "bike", "subway", "drive", "ferry", "walk", "bike", "subway", "drive", "ferry")
> kids <- c("Yes", "Yes", "No", "No", "Yes", "Yes", "No", "No", "Yes", "Yes", "No", "No", "Yes", "No", "Yes")
> distance <- c(1, 12, 5, 25, 7, 2, "", 8, 19, 7, "", 4, 16, 12, 7)
> 
> df = data.frame(commute, kids, distance)
> df
   commute kids distance
1     walk  Yes        1
2     bike  Yes       12
3   subway   No        5
4    drive   No       25
5    ferry  Yes        7
6     walk  Yes        2
7     bike   No         
8   subway   No        8
9    drive  Yes       19
10   ferry  Yes        7
11    walk   No         
12    bike   No        4
13  subway  Yes       16
14   drive   No       12
15   ferry  Yes        7

如果满足以下三个条件:

commute = walk OR bike OR subway OR ferry
AND
kids = Yes
AND
distance is less than 10

然后我想要一个名为 get.flyer 的新列等于“是”。最终的数据框应如下所示:

   commute kids distance get.flyer
1     walk  Yes        1       Yes
2     bike  Yes       12       Yes
3   subway   No        5          
4    drive   No       25          
5    ferry  Yes        7       Yes
6     walk  Yes        2       Yes
7     bike   No                   
8   subway   No        8          
9    drive  Yes       19          
10   ferry  Yes        7       Yes
11    walk   No                   
12    bike   No        4          
13  subway  Yes       16       Yes
14   drive   No       12          
15   ferry  Yes        7       Yes

【问题讨论】:

  • 请尝试关注this

标签: r if-statement dataframe calculated-columns multiple-conditions


【解决方案1】:

我们可以使用%in% 来比较列中的多个元素,&amp; 来检查两个条件是否为真。

library(dplyr)
df %>%
     mutate(get.flyer = c("", "Yes")[(commute %in% c("walk", "bike", "subway", "ferry") & 
           as.character(kids) == "Yes" & 
           as.numeric(as.character(distance)) < 10)+1] )

最好使用stringsAsFactors=FALSE 创建data.frame,因为默认情况下它是TRUE。如果我们检查str(df),我们可以发现所有的列都是factor类。此外,如果有缺失值,可以使用NA 代替NA 来避免将numeric 列的class 转换为其他值。

如果我们重写'df'的创建

distance <- c(1, 12, 5, 25, 7, 2, NA, 8, 19, 7, NA, 4, 16, 12, 7)
df1 <- data.frame(commute, kids, distance, stringsAsFactors=FALSE)

上面的代码可以简化

df1 %>%
    mutate(get.flyer = c("", "Yes")[(commute %in% c("walk", "bike", "subway", "ferry") &
        kids == "Yes" &
        distance < 10)+1] )

为了更好理解,有些人更喜欢ifelse

df1 %>% 
   mutate(get.flyer = ifelse(commute %in% c("walk", "bike", "subway", "ferry") & 
                kids == "Yes" &
                distance < 10, 
                          "Yes", ""))

这也可以通过base R 方法轻松完成

df1$get.flyer <- with(df1, ifelse(commute %in% c("walk", "bike", "subway", "ferry") & 
              kids == "Yes" & 
              distance < 10, 
                       "Yes", ""))

【讨论】:

    【解决方案2】:

    @akrun 已经指出了解决方案。我想以更“完整”的方式呈现它。

    您可以使用ifelse 语句根据一个(或多个)条件创建列。但首先您必须更改距离列中缺失值的“编码”。您使用"" 表示缺失值,但这会将整个列转换为string 并禁止数值比较(distance &lt; 10 是不可能的)。 R表示缺失值的方式是NA,你的distance的列定义应该是:

    distance <- c(1, 12, 5, 25, 7, 2, NA, 8, 19, 7, NA, 4, 16, 12, 7)
    

    ifelse 语句如下所示:

    df$get.flyer <- ifelse(
        ( 
            (df$commute %in% c("walk", "bike", "subway", "ferry")) &
            (df$kids == "Yes")                                     &
            (df$distance < 10)
        ),
        1,  # if condition is met, put 1
        0   # else put 0
    )
    

    可选:考虑以不同的方式对其他列进行编码:

    • 您可以使用 TRUEFALSE 代替 kids 变量的“是”和“否”
    • 您可以使用factor 进行通勤

    【讨论】:

      【解决方案3】:

      例如,检查 first_column_name 是否包含在 second_column_name 中,并将结果写入 new_column

      df$new_column <- apply(df, 1, function(x) grepl(x['first_column_name'], x['second_column_name'], fixed = TRUE))
      

      详情:

      df$new_column <- # create a new column with name new_column on df
      apply(df, 1 # `1` means for each row, `apply(df` means apply the following function on df
      function(x) # Function definition to apply on each row, `x` means input row for each row.
      grepl(x['first_column_name'], x['second_column_name'], fixed = TRUE)) # Body of function to apply, basically run grepl to find if first_column_name is in second_column_name, fixed = TRUE means don't use regular expression just the plain text from first_column_name.
      

      【讨论】:

        猜你喜欢
        • 2020-07-11
        • 1970-01-01
        • 2019-08-27
        • 2020-03-20
        • 1970-01-01
        • 1970-01-01
        • 2019-03-19
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多