[英]Calculate the difference between multiple values belonging to a group
我對R中的一個特定問題有些困惑,對此我只有一個漫不經心而毫無意義的解決方案。 也許有人知道這樣做的更好方法。 可以說我們有一個像這樣的數據框:
x <- c("A", "B", "C", "B", "A", "C", "C", "B", "A", "B", "A", "C")
z <- c(1, 1, 1, 2, 2, 2,3, 3, 3, 4, 4,4)
y <- c(43, 32, 45, 32, 22, 52, 23, 13, 12, 4, 12, 5)
df <- data.frame(x,z,y)
數據如下: plot
我試圖計算取決於z的x分組內的y值之間的差異。 例如,第1組的A和第2組的A(43-22 = 21)與第2組的A和第3組的A(22-12 = 10)之間的差異,依此類推。 我可以這樣做很丑陋:
ordered.df<-df[order(df$z, df$x),]
bl<-ordered.df[ordered.df$z==1,]
bl2<-ordered.df[ordered.df$z==2,]
bl3<-ordered.df[ordered.df$z==3,]
bl4<-ordered.df[ordered.df$z==4,]
first <- bl$y - bl2$y
second <- bl2$y - bl3$y
third <- bl3$y - bl4$y
ycolumn <- c(first,second,third)
xcolumn <- rep(c("A","B","C"),3)
zcolumn <- rep(1:3,each=3)
final.df <- data.frame(xcolumn,zcolumn,ycolumn)
並想知道是否還有更多的電力和可擴展解決方案。
歸根結底,我想算一下正差異的出現:
final.df$lower <- 0
final.df$lower[final.df$ycolumn>0] <- 1
aggregate(lower ~ zcolumn, final.df, sum)
歡迎任何建議! 謝謝!
這是一個data.table單行
setDT(df)[, list(z = z, y_diff = y - shift(y, 1, type = "lead")), by = .(x = x)][ y_diff > 0, list(lower = .N), by = "z"]
# z lower
#1: 1 1
#2: 2 3
#3: 3 2
它能做什么:
setDT(df)
用df
制作一個data.table
[, list(z = z, y_diff = y - shift(y, 1, type = "lead")), by = .(x = x)]
用x分組,從當前y中減去下一個y,並使用結果創建列y_diff
[ y_diff > 0, list(lower = .N), by = "z"]
對於y_diff
大於0的所有行,給y_diff
數(= .N
),按z
分組
您可以為每個組使用dplyr
和mutate
:
library(dplyr)
final.df <- df %>%
group_by(x) %>%
mutate(y = y - lead(y, 1)) %>%
arrange(z, x) %>%
filter(!is.na(y))
final.df
# A tibble: 9 x 3
# Groups: x [3]
x z y
<fct> <dbl> <dbl>
1 A 1 21
2 B 1 0
3 C 1 -7
4 A 2 10
5 B 2 19
6 C 2 29
7 A 3 0
8 B 3 9
9 C 3 18
並對summarise
使用summarise
:
final.df %>%
group_by(z) %>%
summarise(lower = sum(y > 0))
# A tibble: 3 x 2
z lower
<dbl> <dbl>
1 1 1
2 2 3
3 3 2
如果實際數據僅具有少量的組(z),但是具有大量的類別(x),則可以將數據轉換為寬格式並從此處開始。 這是簡單示例的解決方案。
> library(data.table)
> library(reshape2)
>
> df_reshape = dcast(x~z, data=df, value.var="y")
> setDT(df_reshape)
> setnames(df_reshape,c(as.character(seq(1,4,1))),c(paste("x",as.character(seq(1,4,1)), sep="")))
> head(df_reshape)
x x1 x2 x3 x4
1: A 43 22 12 12
2: B 32 32 13 4
3: C 45 52 23 5
> df_reshape[,.(diff1=x1-x2,diff2=x2-x3,diff3=x3-x4),by=x][,.(group1 = sum(diff1>0),group2 =sum(diff2>0),group3 = sum(diff3>0))]
group1 group2 group3
1: 1 3 2
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.