3

データフレームを作成しましたがmy.df、いくつかの基準に基づいて行を選択(または行を削除)したいと思います。この例のデータフレームでは、行1、2、4、7、および8を保持します。具体的には、次のことを行います。

  1. 列3、4、または5に数値を含む行を保持します
  2. 列1と2が空白でなく、ジャンクが含まれていない場合は、行3〜5に欠落しているすべての観測値を含む行を保持します。

私はこれを行うことができますが、私の解決策は非常に複雑であるように思われ、誰かがより効率的なアプローチを提案することを望んでいます。

my.df <- data.frame(C1 = c("group1", "group1",     "",     "", "junk", "junk", "group2",       ""),
                    C2 = c(     "A",      "B",     "",     "",     "", "junk",      "B",      "C"),
                    C3 = c(     100,       NA,     NA,     10,     NA,     NA,       NA,       NA),
                    C4 = c(     200,       NA,     NA,     20,     NA,     NA,      100,       NA),
                    C5 = c(     100,       NA,     NA,     30,     NA,     NA,       NA,        5))

my.df

# the number of missing observations in columns 3-5 is < 3 or
# when the number of missing observations in columns 3-5 is 3 neither column 1 nor 2 is either blank or 'junk'

df.2 <- my.df[ (rowSums(is.na(my.df[,3:5]))  < (ncol(my.df)-2)) | 
               (rowSums(is.na(my.df[,3:5])) == (ncol(my.df)-2) & my.df[,1] != 'junk' & my.df[,2] != 'junk'  & my.df[,1] != '' & my.df[,2] != '') , ]
df.2

私の実際のデータでは、ジャンクと見なされるものは複雑になる可能性があります。したがって、ここで一般化junkして、行1、2、4、7、および8を保持したいと思います。以下のコードは機能しますjunk1junk2

my.df <- data.frame(C1 = c("group1", "group1",     "",     "", "junk2", "junk1", "group2",       ""),
                    C2 = c(     "A",      "B",     "",     "",      "", "junk1",      "B",      "C"),
                    C3 = c(     100,       NA,     NA,     10,      NA,      NA,       NA,       NA),
                    C4 = c(     200,       NA,     NA,     20,      NA,      NA,      100,       NA),
                    C5 = c(     100,       NA,     NA,     30,      NA,      NA,       NA,        5))

my.df

df.3 <- my.df[ (rowSums(is.na(my.df[,3:5]))  < (ncol(my.df)-2)) | 
               (rowSums(is.na(my.df[,3:5])) == (ncol(my.df)-2)  & 
                my.df[,1] != 'junk1' & my.df[,2] != 'junk1'     & 
                my.df[,1] != 'junk2' & my.df[,2] != 'junk2'     &
                my.df[,1] != '' & my.df[,2] != '') 

        , ]
df.3

ここでは、ジャンクと見なされる文字列が非常に多様で複雑になるため、%in%を使用してコードを少し単純化してジャンクをグループ化しようとしましたが、エラーが発生しました。

all.junk <- c("", "junk1", "junk2")

my.df.1 <- my.df[,1]
my.df.2 <- my.df[,2]

my.df.1 <- as.character(my.df.1)
my.df.2 <- as.character(my.df.2)

df.4 <- my.df[ (rowSums(is.na(my.df[,3:5]))  < (ncol(my.df)-2)) | 
               (rowSums(is.na(my.df[,3:5])) == (ncol(my.df)-2) & 
                my.df.1[!(my.df.1%in%all.junk)] & my.df.2[!(my.df.2%in%all.junk)]) , ]
df.4

私が持っている関数型コードを続行して、df.3ジャンクと見なされる文字列ごとに新しい行を追加することもできますが、はるかに効率的な解決策があると思います。

Stackoverflowで同様の質問を見つけましたが、この例のように多くの、または複雑な選択基準を扱っているように思われるものはありません。

提案をありがとうございますが、特にのエラーに関してdf.4です。

4

2 に答える 2

3

これはかなりコンパクトです。すべてがジャンク/nasではないすべての行を保持します。

all.junk=c("junk","")
subset(my.df,!(C1%in%all.junk &
               C2%in%all.junk & 
               is.na(C3) & is.na(C4) & is.na(C5)))

出力

      C1 C2  C3  C4  C5
1 group1  A 100 200 100
2 group1  B  NA  NA  NA
4            10  20  30
7 group2  B  NA 100  NA
8         C  NA  NA   5
于 2012-08-31T22:11:31.367 に答える
1

読みやすさが懸念される場合は、次のコードをリファクタリングできます。

df.3 <- my.df[ (rowSums(is.na(my.df[,3:5]))  < (ncol(my.df)-2)) | 
           (rowSums(is.na(my.df[,3:5])) == (ncol(my.df)-2)  & 
            my.df[,1] != 'junk1' & my.df[,2] != 'junk1'     & 
            my.df[,1] != 'junk2' & my.df[,2] != 'junk2'     &
            my.df[,1] != '' & my.df[,2] != '') 
    , ]

の中へ:

# Rows I want
good.rows = (rowSums(is.na(my.df[,3:5]))  < (ncol(my.df)-2)) | 
           (rowSums(is.na(my.df[,3:5])) == (ncol(my.df)-2)  & 
            my.df[,1] != 'junk1' & my.df[,2] != 'junk1'     & 
            my.df[,1] != 'junk2' & my.df[,2] != 'junk2'     &
            my.df[,1] != '' & my.df[,2] != '') 

df.3 <- my.df[good.rows,]

そしてさらに:

sums.are.fine = (rowSums(is.na(my.df[,3:5]))  < (ncol(my.df)-2)) | 
           (rowSums(is.na(my.df[,3:5])) == (ncol(my.df)-2)

no.junk = my.df[,1] != 'junk1' & my.df[,2] != 'junk1'     & 
            my.df[,1] != 'junk2' & my.df[,2] != 'junk2'     &
            my.df[,1] != '' & my.df[,2] != '') 

good.rows = sums.are.fine & no.junk

df.3 <- my.df[good.rows,]

check.if.sums.are.fine(table.to.check)ブール値を返すcheck.everything(table.to.check)関数と、これらすべてを呼び出して最終結果を返す関数など、別々の関数を作成することもできます。

タイピングの部分が気になる場合、私が気付いたのは、「Ca n't be junk1or junk2or null」のようなものについては、を作成し、bad.values = character()これに不要なすべての値を入力してから、含まれていない値を確認するだけです。 in bad.values(forループを使用しない限り、ソリューションに追加するには多少の作業が必要になる場合があります)。

于 2012-09-01T00:13:58.113 に答える