【问题标题】:Ordering a dataframe by its subsegments按子段排序数据框
【发布时间】:2023-03-05 13:38:01
【问题描述】:

我和我的团队正在处理成千上万个具有相似段的 URL。 某些 URL 在我们感兴趣的位置有一个段(“seg”、复数、“segs”)。其他类似的 URL 在我们感兴趣的位置上有不同的段。 我们需要对由 URL 和相关的唯一段组成的数据框进行排序 在感兴趣的位置,显示这些独特段的频率。

这是一个简化的例子:

 url <- c(1, 3, 1, 4, 2, 3, 1, 3, 3, 3, 3, 2)
 seg <- c("a", "c", "a", "d", "b", "c", "a", "x", "x", "y", "c", "b")
 df <- data.frame(url,seg)

我们正在寻找以下内容:

url freq seg 
 1   3    a   in other words, url #1 appears three times each with a seg = "a",
 2   2    b   in other words: url #2 appears twice each with a seg = "b",
 3   3    c   in other words: url #3 appears three times with a seg = "c", 
 3   2    x                                  two times with a seg = "x", and, 
 3   1    y                                  once with a seg = "y"
 4   1    d   etc.

我可以使用循环和几个小步骤到达那里,但我相信有一种更优雅的方式来做到这一点。这是我的不雅方法:

创建具有 num.unique 行和三列(url、freq、seg)的空数据框

 result <- data.frame(url=0, Freq=0, seg=0)

确定唯一的 URL

 unique.df.url <- unique(df$url)

遍历数据框

 for (xx in unique.df.url) {
   url.seg <- df[which(df$url == unique.df.url[xx]), ] # create a dataframe for each of the unique urls and associated segs
   freq.df.url <- data.frame(table(url.seg))  # summarize the frequency distribution of the segs by url
   result <- rbind(result,freq.df.url)  # append a new data.frame onto the last one
 }

消除数据框中频率 = 0 的行

 result.freq <- result[which(result$Freq |0), ]

按 URL 对数据框进行排序

 result.order <- result.freq[order(result.freq$url), ]

这产生了预期的结果,但由于它太不优雅了,我担心一旦我们扩大规模,所需的时间将会令人望而却步,或者至少是一个问题。有什么建议?

【问题讨论】:

  • 还有reshape2::dcast(df, url + seg ~ "freq")

标签: r subset


【解决方案1】:

在基础 R 中,您可以这样做:

aggregate(freq~seg+url,`$<-`(df,freq,1),sum)
# or aggregate(freq~seg+url, data.frame(df,freq=1),sum)

#   seg url freq
# 1   a   1    3
# 2   b   2    2
# 3   c   3    3
# 4   x   3    2
# 5   y   3    1
# 6   d   4    1

$&lt;- 的诀窍是在任何地方添加一个值为 1 的列 freq,而不更改您的源表。

另一种可能性:

subset(as.data.frame(table(df[2:1])),Freq!=0)
#    seg url Freq
# 1    a   1    3
# 8    b   2    2
# 15   c   3    3
# 17   x   3    2
# 18   y   3    1
# 22   d   4    1

这里我使用[2:1] 来切换列的顺序,以便table 以所需的方式对结果进行排序。

【讨论】:

  • 我理解你的两个答案中的第二个,但是关于你的第一个答案有几点我不明白。我查过“聚合”并认为我理解它;与使用波浪号相同,但加号不是那么多(你是在添加这些向量吗?为什么?);无法完全理解如何解释所有这些的使用。最后,我根本找不到任何对“$
  • '$&lt;-'(df,freq,1)df$freq &lt;- 1 之后返回df,因此它返回相同的df,其中freq 列始终等于1。然后聚合此变量的总和,即与计算行数相同,并将结果存储到输出的freq列中。
  • 这是一个不太聪明的版本:df2 &lt;- df; df2$freq &lt;- 1; aggregate(freq~seg+url, df2, sum)
  • 加号不应被视为加法运算符,在这种情况下,它用于枚举分组变量,我将freqsegurl 相加
  • 我也找不到关于 $&lt;-[&lt;-[[&lt;- 等运算符的好的文档。如果它尚不存在,那可能会成为一个很棒的帖子,我会调查的。但简而言之,在 R 中,当您不进行“直接”分配时,例如 a &lt;- b,而是像 a[2] &lt;- ba$x &lt;- bnames(a) &lt;- c("x","y") 之类的东西,您实际上分别调用 a &lt;- '[&lt;-'(a,b,value=2)a &lt;- '[&lt;-'(a,x,b)a &lt;- 'names&lt;-'(a,c("x","y")) 在引擎盖下。了解这一点会带来很多可能性。
【解决方案2】:

一个选项可以是使用tabletidyr::gather 来获取OP 所需格式的数据:

library(tidyverse)
table(df) %>% as.data.frame() %>% 
  filter(Freq > 0 ) %>%
  arrange(url, desc(Freq))


#   url seg  Freq
# 1   1   a     3
# 2   2   b     2
# 3   3   c     3
# 4   3   x     2
# 5   3   y     1
# 6   4   d     1

df %>% group_by(url, seg) %>%
  summarise(freq = n()) %>%
  arrange(url, desc(freq))

# # A tibble: 6 x 3
# # Groups: url [4]
#    url seg      freq
#   <dbl> <fctr> <int>
# 1  1.00 a          3
# 2  2.00 b          2
# 3  3.00 c          3
# 4  3.00 x          2
# 5  3.00 y          1
# 6  4.00 d          1

【讨论】:

  • 我没有得到您的第一个解决方案,通过收集单个列,您只是创建了一个附加列,您在第 3 步将其删除。
  • @Moody_Mudskipper 感谢您指出这一点。我已经纠正了。我认为当我误解问题并尝试使用gather 进行处理时,剩下的就是这些了。您的回答也令人印象深刻。
【解决方案3】:

或粘贴并点击:

url <- c(1, 3, 1, 4, 2, 3, 1, 3, 3, 3, 3, 2)
seg <- c("a", "c", "a", "d", "b", "c", "a", "x", "x", "y", "c", "b")
df <- data.frame(url,seg)

want <- tapply(url, INDEX = paste(url, seg, sep = "_"), length)
want <- data.frame(do.call(rbind, strsplit(names(want), "_")), want)
colnames(want) <- c("url", "seg", "freq")
want <- want[order(want$url, -want$freq), ]
rownames(want) <- NULL # needed?
want <- want[ , c("url", "freq", "seg")] # needed?
want

【讨论】:

    【解决方案4】:

    下面的代码对你来说会更好吗?

    library(dplyr)
    df %>% group_by(url, seg) %>% summarise(n()) 
    

    【讨论】:

    • 我已经由 dplyr 和 magrittr 加载(相关问题中的 cmets 引用),但我收到“group_by”错误。你能解释一下吗?
    【解决方案5】:
    url <- c(1, 3, 1, 4, 2, 3, 1, 3, 3, 3, 3, 2)
    seg <- c("a", "c", "a", "d", "b", "c", "a", "x", "x", "y", "c", "b")
    df <- data.frame(url,seg)
    
    library(dplyr)
    
    df %>% count(url, seg) %>% arrange(url, desc(n))
    
    # # A tibble: 6 x 3
    #     url seg       n
    #   <dbl> <fct> <int>
    # 1     1 a         3
    # 2     2 b         2
    # 3     3 c         3
    # 4     3 x         2
    # 5     3 y         1
    # 6     4 d         1
    

    【讨论】:

    • 我已经由 dplyr 和 magrittr 加载(相关问题中的 cmets 引用),但我得到“计数错误(., url, seg):找不到函数“count”'。你能解释一下吗?
    • 尝试改用dplyr::count(...)。或者尝试刷新您的 R 会话并仅加载 dplyr 包。还要检查你是否成功地加载了包。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2018-07-11
    • 2022-11-13
    • 2021-12-27
    • 2016-08-30
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多