データフレームがあります(all_data
)サイト(1 ...からn)とそのスコアのリストがあります(例:.
site score
1 10
1 11
1 12
4 10
4 11
4 11
8 9
8 8
8 7
カウンターのように、サイトの各レベルに番号順に番号を付ける列を作成したいと思います。この例では、サイト(1、4、および8)の「番号」列に1から3までの対応するカウンターがあります。
site score number
1 10 1
1 11 1
1 12 1
4 10 2
4 11 2
4 11 2
8 9 3
8 8 3
8 7 3
これは簡単に解決できるはずですが、まだ方法が見つかりません。
Data$number <- as.numeric(as.factor(Data$site))
を試してください
補足:私と@Chaseのソリューションと、@ DWinのソリューションの違いは、番号の順序です。両方とも as.factor
とfactor
は自動的にレベルを並べ替えますが、@ DWinのソリューションでは発生しません。
Dat <- data.frame(site = rep(c(1,8,4), each = 3), score = runif(9))
Dat$number <- as.numeric(factor(Dat$site))
Dat$sitenum <- match(Dat$site, unique(Dat$site) )
与える
> Dat
site score number sitenum
1 1 0.7377561 1 1
2 1 0.3131139 1 1
3 1 0.7862290 1 1
4 8 0.4480387 3 2
5 8 0.3873210 3 2
6 8 0.8778102 3 2
7 4 0.6916340 2 3
8 4 0.3033787 2 3
9 4 0.6552808 2 3
他の2つのオプション:
1).GRP
パッケージのdata.table
関数の使用:
library(data.table)
setDT(dat)[, num := .GRP, by = site]
以下のサンプルデータセットを使用すると、次のようになります。
> dat
site score num
1: 1 0.14945795 1
2: 1 0.60035697 1
3: 1 0.94643075 1
4: 8 0.68835336 2
5: 8 0.50553372 2
6: 8 0.37293624 2
7: 4 0.33580504 3
8: 4 0.04825135 3
9: 4 0.61894754 3
10: 8 0.96144729 2
11: 8 0.65496051 2
12: 8 0.51029199 2
2)dplyr
からgroup_indices
関数を使用する:
dat$num <- group_indices(dat, site)
または、非標準の評価を回避したい場合:
library(dplyr)
dat %>%
mutate(num = group_indices_(dat, .dots = c('site')))
その結果:
site score num
1 1 0.42480366 1
2 1 0.98736177 1
3 1 0.35766187 1
4 8 0.06243182 3
5 8 0.55617002 3
6 8 0.20304632 3
7 4 0.90855921 2
8 4 0.25215078 2
9 4 0.44981251 2
10 8 0.60288270 3
11 8 0.46946587 3
12 8 0.44941782 3
ご覧のとおり、dplyr
はグループ番号の順序が異なります。
グループが変更されるたびに別の番号が必要な場合は、他にもいくつかのオプションがあります。
1)ベースR:
# option 1:
dat$num <- cumsum(c(TRUE, head(dat$site, -1) != tail(dat$site, -1)))
# option 2:
x <- rle(dat$site)$lengths
dat$num <- rep(seq_along(x), times=x)
2)data.table
パッケージを使用:
library(data.table)
setDT(dat)[, num := rleid(site)]
その結果、次のようになります。
> dat
site score num
1 1 0.80817855 1
2 1 0.07881334 1
3 1 0.60092828 1
4 8 0.71477988 2
5 8 0.51384565 2
6 8 0.72011650 2
7 4 0.74994627 3
8 4 0.09564052 3
9 4 0.39782587 3
10 8 0.29446540 4
11 8 0.61725367 4
12 8 0.97427413 4
使用データ:
dat <- data.frame(site = rep(c(1,8,4,8), each = 3), score = runif(12))
これはかなり効率的で理解しやすいはずです。
Dat$sitenum <- match(Dat$site, unique(Dat$site))
@Jaapからのデータを使用すると、dense_rank()
を使用した別のdplyr
の可能性は次のようになります。
_dat %>%
mutate(ID = dense_rank(site))
site score ID
1 1 0.1884490 1
2 1 0.1087422 1
3 1 0.7438149 1
4 8 0.1150771 3
5 8 0.9978203 3
6 8 0.7781222 3
7 4 0.4081830 2
8 4 0.2782333 2
9 4 0.9566959 2
10 8 0.2545320 3
11 8 0.1201062 3
12 8 0.5449901 3
_
または、rleid()
のようなdplyr
アプローチで、データを最初に配置します。
_dat %>%
arrange(site) %>%
mutate(ID = {ID_rleid = rle(site); rep(seq_along(ID_rleid$lengths), ID_rleid$lengths)})
site score ID
1 1 0.1884490 1
2 1 0.1087422 1
3 1 0.7438149 1
4 4 0.4081830 2
5 4 0.2782333 2
6 4 0.9566959 2
7 8 0.1150771 3
8 8 0.9978203 3
9 8 0.7781222 3
10 8 0.2545320 3
11 8 0.1201062 3
12 8 0.5449901 3
_
または、別のrleid()
のようなdplyr
の可能性で、データが最初に配置されます。
_dat %>%
arrange(site) %>%
mutate(ID = with(rle(site), rep(seq_along(lengths), lengths)))
_
_base R
_と同じ:
_df$ID <- with(rle(df$site), rep(seq_along(lengths), lengths))
_
または、duplicated()
およびcumsum()
を使用します。
_df %>%
mutate(ID = cumsum(!duplicated(site)))
_
_base R
_と同じ:
_df$ID <- cumsum(!duplicated(df$site))
_
サイトを係数に変換してから、その係数の数値または整数値を返すことができます。
dat <- data.frame(site = rep(c(1,4,8), each = 3), score = runif(9))
dat$number <- as.integer(factor(dat$site))
dat
site score number
1 1 0.5305773 1
2 1 0.9367732 1
3 1 0.1831554 1
4 4 0.4068128 2
5 4 0.3438962 2
6 4 0.8123883 2
7 8 0.9122846 3
8 8 0.2949260 3
9 8 0.6771526 3
data.table
パッケージを使用した別のソリューション。
Jaapによって提供されるより完全なデータセットの例:
setDT(dat)[, number := frank(site, ties.method = "dense")]
dat
site score number
1: 1 0.3107920 1
2: 1 0.3640102 1
3: 1 0.1715318 1
4: 8 0.7247535 3
5: 8 0.1263025 3
6: 8 0.4657868 3
7: 4 0.6915818 2
8: 4 0.3558270 2
9: 4 0.3376173 2
10: 8 0.7934963 3
11: 8 0.9641918 3
12: 8 0.9832120 3
それを行う別の方法。 Rについてほとんど知らなくても簡単に入手できると思います。
library(dplyr)
df <- data.frame('site' = c(1, 1, 1, 4, 4, 4, 8, 8, 8))
df <- mutate(df, 'number' = cumsum(site != lag(site, default=-1)))