我有一个data.table,如下所示
col1 col2 col3
1 A 23
2 B 20
3 A 23
4 B 0
5 B 20
6 A 0
7 C 10
当col2匹配时,我想用col3的值替换所有0
。例如,在这种情况下,row4, col3
应替换为20
,而row6,col3
应替换为23
编辑:
由于row6,col2
是A
,我想要col3
对应col2==A
答案 0 :(得分:2)
OP已澄清他希望将col3
中的任何零值替换为每个col2
组的最常见非零值。
问题标记为data.table
,这里有一些data.table
解决方案:
ifelse()
library(data.table)
# find most frequent non-zero value by group
tmp <- DT[col3 != 0, .N, by = .(col2, col3)][order(N), .(col3 = last(col3)), by = col2]
tmp
col2 col3 1: C 10 2: A 23 3: B 20
# update on join
DT[tmp, on = .(col2), col3 := ifelse(col3 == 0, i.col3, col3)][]
col1 col2 col3 1: 1 A 23 2: 2 B 20 3: 3 A 23 4: 4 B 20 5: 5 B 20 6: 6 A 23 7: 7 C 10
ifelse()
有一个变体用更复杂的连接替换ifelse()
表达式:
tmp <- DT[col3 != 0, .N, by = .(col2, col3)][order(N), last(col3), by = col2][, col3 := 0]
tmp
col2 V1 col3 1: C 10 0 2: A 23 0 3: B 20 0
DT[tmp, on = .(col2, col3), col3 := V1][]
col1 col2 col3 1: 1 A 23 2: 2 B 20 3: 3 A 23 4: 4 B 20 5: 5 B 20 6: 6 A 23 7: 7 C 10
zoo::na.aggregate()
和raster::modal()
zoo
包提供了几种替换NA
值的功能。
DT[col3 == 0, col3 := NA][
# replace NA by modal value (most frequent value) per group
, col3 := as.integer(zoo::na.aggregate(col3, FUN = raster::modal)), by = col2][]
col1 col2 col3 1: 1 A 23 2: 2 B 20 3: 3 A 23 4: 4 B 20 5: 5 B 20 6: 6 A 23 7: 7 C 10
请注意,此解决方案可能会在边缘情况下返回前两个解决方案的不同结果:
col2
组在col3
中仅包含零值,则该组中没有最常见的非零值。然后这些零值返回为NA
,而其他两个解决方案保持不变。col3
中有两个或多个值同样频繁出现,则不会定义哪个值优先于另一个。答案 1 :(得分:1)
使用zoo
na.locf
library(zoo)
df$col3[df$col3==0]=NA # 1st replace 0 to NA
df=df[order(df$col2,df$col3),] #order df
df$col3=na.locf(df$col3)
df[order(df$col1),]
col1 col2 col3
1 1 A 23
2 2 B 20
3 3 A 23
4 4 B 20
5 5 B 20
6 6 A 23
7 7 C 10
或者使用dplyr
:
df%>%group_by(col2)%>%mutate(col3=ifelse(col3==0,unique(col3[col3!=0]),col3))