web-dev-qa-db-ja.com

複数の列の複数の条件に基づいて新しい列を作成するにはどうすればよいですか?

他の列のいくつかの条件に基づいて、データフレームに新しい列を追加しようとしています。次のデータがあります。

> 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

次の3つの条件が満たされている場合:

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
7
Ankie

_%in%_を使用して列の複数の要素を比較し、_&_を使用して両方の条件がTRUEであるかどうかを確認できます。

_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] )
_

デフォルトではTRUEであるため、_data.frame_を_stringsAsFactors=FALSE_で作成することをお勧めします。 str(df)を確認すると、すべての列がfactorクラスであることがわかります。また、欠損値がある場合は、_""_の代わりにNAを使用して、class列のnumericを別の列に変換しないようにすることができます。

「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", ""))
_
11
akrun

ソリューションはすでに@akrunによって指摘されています。もっと「包み込んだ」形で提示したい。

ifelseステートメントを使用して、1つ(または複数)の条件に基づいて列を作成できます。ただし、最初に距離列の欠損値の「エンコード」を変更する必要があります。使いました ""は欠損値を示しますが、列全体がstringに変換され、数値比較が禁止されます(distance < 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
)

オプション:他の列も別の方法でエンコードすることを検討してください:

  • TRUE変数に「はい」と「いいえ」の代わりにFALSEkidsを使用できます
  • 通勤にはfactorを使用できます
7
Tw UxTLi51Nus

例: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.
0
Tomer Ben David