按组返回基R中最频繁的字符串

按组返回基R中最频繁的字符串,r,R,我有一个数据集,我想为a的每个唯一条目返回列b中最频繁的条目,其中两列都是字符向量。如果b中的两个条目对于a中的一个唯一条目的频率相同,我想在单独的列中返回b中的两个条目(下面是所需的输出) 这类似于所问的问题,但该问题的答案都使用tidyverse。我讨厌tidyverse,因为tidyverse对象破坏了我项目中的其他东西。寻找基本的R解决方案(并避免谈论tidyverse的优点) 我的数据如下所示: a <- as.character(c(rep(1:3,4))) b <- c

我有一个数据集,我想为
a
的每个唯一条目返回列
b
中最频繁的条目,其中两列都是字符向量。如果
b
中的两个条目对于
a
中的一个唯一条目的频率相同,我想在单独的列中返回
b
中的两个条目(下面是所需的输出)


这类似于所问的问题,但该问题的答案都使用tidyverse。我讨厌tidyverse,因为tidyverse对象破坏了我项目中的其他东西。寻找基本的R解决方案(并避免谈论tidyverse的优点)

我的数据如下所示:

a <- as.character(c(rep(1:3,4)))
b <- c("A","A","A",
       "B","B","B",
       "A","B","A",
       "A","B","B")
df <- data.frame(a,b)

 a b
 1 A
 2 A
 3 A
 1 B
 2 B
 3 B
 1 A
 2 B
 3 A
 1 A
 2 B
 3 B
a继续:

好的,我们现在有了每-
b
的计数。意识到这里可能有更多,比如:

# A B C
# 2 2 1
所以我将把这个命名向量简化为具有最高值的向量:

# Browse[2]> 
( tb <- tb[ tb == max(tb) ] ) # no change here, but had there been a third value in 'b' ...
# A B 
# 2 2 
现在,我们已经在内部进行了探索,让我们结束这一切

by(df, df$a, function(x) {
   tb <- table(x$b)
   tb <- tb[ tb == max(tb) ]
   data.frame(a = x$a[1], b = names(tb), r = seq_along(tb))
})
# df$a: 1
#   a b r
# 1 1 A 1
# ------------------------------------------------------------ 
# df$a: 2
#   a b r
# 1 2 B 1
# ------------------------------------------------------------ 
# df$a: 3
#   a b r
# 1 3 A 1
# 2 3 B 2
顺便说一句:对于
data.frame
rbind.data.frame
,默认情况下,它们都会为您提供
因子
s。如果您不想要它们,那么:

do.call(rbind.data.frame, c(by(df, df$a, function(x) {
  tb <- table(x$b)
  tb <- tb[ tb == max(tb) ]
  data.frame(a = x$a[1], b = names(tb), r = seq_along(tb),
             stringsAsFactors = FALSE)
}), stringsAsFactors=FALSE))
#     a b r
# 1   1 A 1
# 2   2 B 1
# 3.1 3 A 1
# 3.2 3 B 2
do.call(rbind.data.frame,c)by(df,df$a,function(x){
tb继续从:

好的,我们现在有了每-
b的计数。意识到这里可能有更多,比如:

# A B C
# 2 2 1
所以我将把这个命名向量简化为具有最高值的向量:

# Browse[2]> 
( tb <- tb[ tb == max(tb) ] ) # no change here, but had there been a third value in 'b' ...
# A B 
# 2 2 
现在,我们已经在内部进行了探索,让我们结束这一切

by(df, df$a, function(x) {
   tb <- table(x$b)
   tb <- tb[ tb == max(tb) ]
   data.frame(a = x$a[1], b = names(tb), r = seq_along(tb))
})
# df$a: 1
#   a b r
# 1 1 A 1
# ------------------------------------------------------------ 
# df$a: 2
#   a b r
# 1 2 B 1
# ------------------------------------------------------------ 
# df$a: 3
#   a b r
# 1 3 A 1
# 2 3 B 2
顺便说一句:对于
data.frame
rbind.data.frame
,默认情况下,它们都会为您提供
因子
s。如果您不需要它们,则:

do.call(rbind.data.frame, c(by(df, df$a, function(x) {
  tb <- table(x$b)
  tb <- tb[ tb == max(tb) ]
  data.frame(a = x$a[1], b = names(tb), r = seq_along(tb),
             stringsAsFactors = FALSE)
}), stringsAsFactors=FALSE))
#     a b r
# 1   1 A 1
# 2   2 B 1
# 3.1 3 A 1
# 3.2 3 B 2
do.call(rbind.data.frame,c)by(df,df$a,function(x){

tb我们可以在
base R

tbl <- table(df)
ifelse(tbl[,1] == tbl[,2], toString(colnames(tbl)), colnames(tbl)[max.col(tbl)])

tbl我们可以在
base R

tbl <- table(df)
ifelse(tbl[,1] == tbl[,2], toString(colnames(tbl)), colnames(tbl)[max.col(tbl)])

tbl另一个
base
备选方案

创建列联表并转换为数据框:
as.data.frame(table(df))

使用
ave
按组选择具有最大值的行

使用
ave
创建一个“时间”变量,以“区分同一组中的多个记录”(请参见
?重塑

将相关变量重塑为宽变量

d <- as.data.frame(table(df))
d2 <- d[d$Freq == ave(d$Freq, d$a, FUN = max), ]
d2$time <- ave(d2$a, d2$a, FUN = seq_along)
reshape(d2[ , c("a", "b", "time")], idvar = "a", direction = "wide")

#   a b.1  b.2
# 1 1   A <NA>
# 3 3   A    B
# 5 2   B <NA>

d另一个
base
备选方案

创建列联表并转换为数据框:
as.data.frame(table(df))

使用
ave
按组选择具有最大值的行

使用
ave
创建一个“时间”变量,以“区分同一组中的多个记录”(请参见
?重塑

将相关变量重塑为宽变量

d <- as.data.frame(table(df))
d2 <- d[d$Freq == ave(d$Freq, d$a, FUN = max), ]
d2$time <- ave(d2$a, d2$a, FUN = seq_along)
reshape(d2[ , c("a", "b", "time")], idvar = "a", direction = "wide")

#   a b.1  b.2
# 1 1   A <NA>
# 3 3   A    B
# 5 2   B <NA>


d“该问题的答案都使用tidyverse”:
by
base
。另请参见@Henrik,我熟悉另一个问题中的
by
解决方案。但是,即使在该答案中,响应者也承认,要获得
by
解决方案的输出,使其看起来与所需的输出类似,这是一个挑战。如果您可以修改该输出,使其看起来与所需的ou类似t如上所述,这将很有帮助。您是否总是在
b
列中只有两个不同的值?否则,“其中
b
中的两个条目的频率相同”可能是含糊不清的……RyDaa歉疚,你能建议重新措辞吗?我真的只想考虑栏<代码> >代码> >代码> > <代码> A >代码> A < <代码> > <代码> B >代码>条目>代码> B <代码>。“这个问题的答案都用TidiVIEW”。:
by
base
。另请参见@Henrik,我熟悉另一个问题中的
by
解决方案。但是,即使在该答案中,响应者也承认,要获得
by
解决方案的输出,使其看起来与所需的输出类似,这是一个挑战。如果您可以修改该输出,使其看起来与所需的ou类似t如上所述,这将很有帮助。您是否总是在
b
列中只有两个不同的值?否则,“其中
b
中的两个条目的频率相同”可能是含糊不清的……Ryorda歉意,你能建议重新措辞吗?我真的只想考虑栏<代码> >代码> >代码> A <代码> >代码< >代码> b >代码> b >代码> b>代码>。谢谢,但是我特别希望避免使用TidiVIEW解决方案。当我运行上面的代码时,它抛出了这个错误:
error in use方法(“groups”):没有适用于应用于类“character”的对象的“groups”方法。
as.data.frame
data.frame
tible
之间通常有两个区别(1)
tibble
s不保留行名,正如
mtcars
tbl_-df(mtcars)
(2)
class(mtcars)
“data.frame”
,而
类(tbl_-df(mtcars))
c(“tbl_-df”,“tbl”,“data.frame”)
,所有其他差异都是在将其打印到控制台时处理的。因此,如果您的数据没有行名称,唯一的区别就是在类中添加了
tbl_df
tbl
。如果您将
表和
移动到
外部
,则不必为每个组运行它们。
d如果速度足够快一个问题,我们可能会这样做,
data.table
(它不会“破坏”事物,这是OP反对
tidyverse
)的论点;+1给出了一个好的、彻底的答案。感谢这一点,但是我特别希望避免使用tidyverse解决方案。另外,当我运行上述代码时,它会抛出以下错误:
错误在UseMethod中(“组”):没有适用于“character”
类对象作为.data.frame
的“组”的方法。
数据.frame
tibble
(1)
tibble
之间通常有两种区别