2016-05-04 7 views
2

論理/バイナリデータフレームの同じ列名をマージします。つまり、出力は4列(リンゴ、キウイ、バナナ、オレンジ)のデータフレームでなければなりません。 は次のように私は論理的なデータフレームを持って

は、私が試した:

testmerge <- df[, !duplicated(colnames(df))] 

しかし、出力は私が探したものではありません。同じ列名が与えられた行ごとに、少なくとも1つのTRUEがある限り、出力はTrueでなければなりません。同じ列名が与えられた行ごとに、TRUEが0の場合はFalseにする必要があります。

intanceの最初の行の最初の列は、FALSEではなくTRUEにする必要があります。

望ましくないtestmerge出力:

apple kiwi banana orange 
1 FALSE FALSE FALSE FALSE 
2 TRUE TRUE TRUE FALSE 
3 FALSE TRUE FALSE FALSE 

所望の出力:

apple kiwi banana orange 
1 TRUE TRUE TRUE FALSE 
2 TRUE TRUE TRUE FALSE 
3 FALSE TRUE FALSE FALSE 

複製のデータフレーム:あり

test <- structure(list(apple = c(FALSE, TRUE, FALSE), apple = c(TRUE, TRUE, 
FALSE), apple = c(FALSE, TRUE, FALSE), kiwi = c(FALSE, TRUE, TRUE 
), kiwi = c(TRUE, TRUE, TRUE), banana = c(FALSE, TRUE, FALSE), banana = c(TRUE, 
FALSE, FALSE), banana = c(TRUE, TRUE, FALSE), apple = c(TRUE, TRUE, 
FALSE), orange = c(FALSE, FALSE, FALSE)), .Names = c("apple", "apple", 
"apple", "kiwi", "kiwi", "banana", "banana", "banana", "apple", "orange"), row.names = c(NA, 
-3L), class = "data.frame") 

答えて

3

とrowSums:私たちはdatafame果物の名前に基づいて、その後、計算rowSumsをサブセット化されている

as.data.frame(
    sapply(unique(colnames(test)), 
     function(i){ 
      rowSums(test[, grepl(i, colnames(test)), drop = FALSE]) > 0}) 
) 

#output 
# apple kiwi banana orange 
# 1 TRUE TRUE TRUE FALSE 
# 2 TRUE TRUE TRUE FALSE 
# 3 FALSE TRUE FALSE FALSE 

。 TRUEは1、FALSEは0なので、0より大きいrowSumsは少なくとも1つのTRUE値を持ちます。私はdrop = FALSEを持っているので、サブセットはorangeのような場合にはデータフレームとして残ります。

注: データが長い場合は、は(リデュース)、より良い機能しますが、データが広い、その後rowSums()が、より効率的である場合@akrunによってソリューション。

2

これを達成するために、多分、より効率的な方法が、ここでは試して

です

make.uniqueを使用してカラム名をユニークなものに変換し、ロングフォーマットに変換し、ローIDとカラム名(再度ユニークにする)で条件を確認してから、ワイドフォーマットに戻すことをお勧めします。 sapply使用

library(data.table) 
setnames(setDT(test), make.unique(names(test))) # Make column names unique 
res <- melt(test[, id := .I], id = "id" # Add a row index and melt by it 
      )[, sum(value) > 0, # Check condition >> 
       by = .(id, Names = sub("\\..*", "", variable))] # by row id and unique names 
dcast(res, id ~ Names, value.var = "V1") # Convert back to wide format 
# id apple banana kiwi orange 
# 1: 1 TRUE TRUE TRUE FALSE 
# 2: 2 TRUE TRUE TRUE FALSE 
# 3: 3 FALSE FALSE TRUE FALSE 
+0

おかげでこれは美しいです。このソリューション – S12000

2

別のオプションは、任意のTRUEが各列に存在するかどうかをチェックするReduceを使用し、数値指標に基づいlist、サブセットを通じてlist、ループにそれのnamesによってsplitに、データセットの列の配列であろう。 (| `、テスト[i]は、`) `

sapply(split(seq_along(test), names(test)), function(i) Reduce(`|`, test[i])) 
#  apple banana kiwi orange 
#[1,] TRUE TRUE TRUE FALSE 
#[2,] TRUE TRUE TRUE FALSE 
#[3,] FALSE FALSE TRUE FALSE 
+1

のための多くは、'削減します! – zx8754

+1

このソリューションのおかげで – S12000

関連する問題