3

私は非常に複雑な問題で立ち往生しています。id、info、rownum の 3 行のデータ フレームがあります。データは次のようになります。

id   info   row
 1      a     1
 1      b     2
 1      c     3
 2      a     4
 3      b     5
 3      a     6
 4      b     7
 4      c     8

私が今やりたいことは、行の1つに情報が含まれている場合、1つのIDの他のすべての行を削除することですa。これは、たとえば、行1の列情報に値aが含まれているため、行23を削除する必要があることを意味します。情報値は順序付けされておらず (id 3/行 5 & 6)、他のデータ制限により順序付けできないことに注意してください。

forループを使用してケースを解決しました:

# select all id containing an "a"-value 
a_val <- data$id[grep("a", data$info)]

# check for every id containing an "a"-value
for(i in a_val) {

   temp_data <- data[which(data$id == i),]

   # only go on if the given id contains more than one row
   if (nrow(temp_data) > 1) {

      for (ii in nrow(temp_data)) {

         if (temp_data$info[ii] != "a") {
            temp <- temp_data$row[ii]

            if (!exists("delete_rows")) {
               delete_rows <- temp
            } else {
               delete_rows <- c(delete_rows, temp)
            }
         }
      }
   }
}

私のソリューションは非常にうまく機能します。それにもかかわらず、元のデータには 70 万行を超える行と、「a」値を持つ 15 万行を超える行が含まれているため、非常に非常に遅くなります。

4 コアのforeachループを使用して高速化することもできますが、誰かがより良い解決策のヒントを教えてくれるかもしれません。

よろしく、
アルネ

[アップデート]

結果は次のようになります。

id   info   row
 1      a     1
 2      a     4
 3      a     6
 4      b     7
 4      c     8
4

5 に答える 5

2

data.tableパッケージを調査することをお勧めします。

編集:row変数がデータ内の各行の連番ではない場合(私が想定したように)、そのような変数を作成して元の行の順序を取得できます:

library(data.table)
# Create data.table of your data
dt <- as.data.table(data)
# Create index to maintain row order
dt[, idx := seq_len(nrow(dt))]
# Set a key on id and info
setkeyv(dt, c("id", "info"))
# Determine unique ids
uid <- dt[, unique(id)]
# subset your data to select rows with "a"
dt2 <- dt[J(uid, "a"), nomatch = 0]
# identify rows of dataset where the id doesn't have an "a"
dt3 <- dt[J(dt2[, setdiff(uid, id)])]
# rbind those two data.tables together
(dt4 <- rbind(dt2, dt3))

#    id info row idx
# 1:  1    a   1   1
# 2:  2    a   4   4
# 3:  3    a   6   6
# 4:  4    b   7   7
# 5:  4    c   8   8

# And if you need the original ordering of rows,
dt5 <- dt4[order(idx)]

data.tableにキーを設定すると、キーの列に従って行が並べ替えられることに注意してください。最後のステップ(作成dt5)は、行の順序を元に戻します。

于 2012-11-26T11:42:27.553 に答える
2

ここに考えられる解決策の 1 つがあります。

最初に次を含むidsを見つけます。info"a"

ids <- with(data, unique(id[info == "a"]))

データをサブセット化します。

subset(data, (id %in% ids & info == "a") | !id %in% ids)

出力:

  id info row
1  1    a   1
4  2    a   4
6  3    a   6
7  4    b   7
8  4    c   8

別の解決策 (解読するのが難しいかもしれません):

subset(data, info == "a" | !rep.int(tapply(info, id, function(x) any(x == "a")),
                                    table(id)))

. @BenBarnes は、このソリューションは、データ フレームが に従って順序付けされている場合にのみ機能することを発見しましたid

于 2012-11-26T11:37:56.347 に答える
1

これを使用する方法は次のddplyとおりです。

df <- read.table(text="id   info   row
 1      a     1
 1      b     2
 1      c     3
 2      a     4
 3      b     5
 3      a     6
 4      b     7
 4      c     8",header=TRUE)


library("plyr")
ddply(df,.(id),subset,rep(!'a'%in%info,length(info))|info=='a')

戻り値:

  id info row
1  1    a   1
2  2    a   4
3  3    a   6
4  4    b   7
5  4    c   8
于 2012-11-26T11:44:57.880 に答える
0

df がこれ (上記の RE Sacha)の場合、最初に出現したインデックスを見つけるだけのmatchを使用します。

df <- read.table(text="id   info   row
 1      a     1
 1      b     2
 1      c     3
 2      a     4
 3      b     5
 3      a     6
 4      b     7
 4      c     8",header=TRUE)


# the first info row matching 'a' and all other rows that are not 'a'
with(df, df[c(match('a',info), which(info != 'a')),])

  id info row
1  1    a   1
2  1    b   2
3  1    c   3
5  3    b   5
7  4    b   7
8  4    c   8
于 2012-11-26T16:47:21.853 に答える
-1

サブセットを試してみてください。使い方は非常に簡単で、問題を解決します。

サブセット化する列の値を指定するだけで済みます。代わりに、さらに列を選択することもできます。

http://stat.ethz.ch/R-manual/R-devel/library/base/html/subset.html

http://www.statmethods.net/management/subset.html

于 2012-11-26T11:22:34.030 に答える