【问题标题】:Combining rows based on the string in one of the columns根据其中一列中的字符串组合行
【发布时间】:2017-06-19 10:53:55
【问题描述】:

我的数据如下:

> dput(test_data)
structure(list(`10` = c(0, 0, 0, 0, 0, 1, 0.22123412423, 0.0123915695, 
0.0126915225, 0.4312, 1), `34` = c(0, 0, 0, 0, 0, 0.323256312, 
0.32423561, 0.44451256, 0.33623498, 0.21341411, 0.321223), `59` = c(0.232, 
0.57192, 0, 0, 0, 0.31312334, 0.2775713, 0.1311453, 0.63215713, 
0.4423123, 0.132212), `84` = c(1, 1, 1, 0, 1, 0, 1, 1, 1, 1, 
0), `110` = c(0.55345123, 0.689875, 0.423415551, 1, 0.444532121, 
0, 0.01186404, 0.22132204, 0.21186404, 0, 0), `134` = c(0.234126, 
0.33347267, 0.35321234, 0.4123412, 0.333412666, 0, 0, 0, 0.3123, 
0, 0), `165` = c(0.1147189, 0.12343, 0.3155, 0.2755712, 0.123, 
0, 0, 0, 0, 0, 0), `199` = c(0.1236836, 0.0058933, 0, 0.1344607, 
0, 0, 0, 0, 0, 0, 0), Group = c("Train", "Bicycle", "Car", "Bicycle", 
"Bicycle", "Car", "Bicycle", "Train", "Car", "Train", "Train"
)), .Names = c("10", "34", "59", "84", "110", "134", "165", "199", 
"Group"), row.names = c("Mark_1", "Greg_1", "Tim_1", "Tom_1", 
"Sim_1", "Karl_1", "Moham_1", "Teraq_1", "Jake_1", "Sonya_1", 
"Monique_1"), class = "data.frame")

我想从同一个Group 中提取行并将它们组合成一行。在这种情况下, row.names 并不重要。应该使用组作为行名。当然有些组有更多的成员(尤其是在我的真实数据中),所以特定列中的缺失值应该用NA's 填充。

例如,GregTomSimMoham 的值应位于名称 Bicycle 下的一行中。

预期输出;

我们有 4 名成员 Bicycle。每个成员都有 8 个值 = 8 列。因此,作为输出,我们应该有一个 row.name=Bicycle 和 32 列,其中的值来自这 4 个成员。我们应该对所有组做同样的事情。

编辑:

所以我希望发布类似RechlayWietze314 的内容。有什么办法可以删除那些NA 值并将列数保持在最大成员数乘以8。我不关心colnames 以及来自哪个/列值。

【问题讨论】:

  • 我想将0 的值保留为0,但我认为在我的真实数据中不应该有任何0。应该只取所有列。
  • 所以,正如我提到的,我们采用Bicycle 组。我们有这个小组的 4 名成员。每个成员都有 8 个值 = 8 列。因此,作为输出,我们应该有一个 row.name=Bicycle 和 32 列,其中的值来自这 4 个成员。我们可以使用“给予”这个值的人的名字来命名这些列。例如Greg_1_10Greg_1_34、.....、Tom_1_10、...、Tom_1_110
  • 看起来像是某种long to wide 转换。
  • 你能显示预期的输出吗
  • 如我所见,我没有正确解释。让我向您展示预期的输出。需要 3 分钟。

标签: r


【解决方案1】:

使用tidyr 函数gatherspread

library(tidyr)
library(dplyr)

result <- test_data %>% mutate(person = row.names(test_data)) %>% 
  gather(key, value, -Group, -person) %>%
  mutate(column = paste0(person,'_',key)) %>%
  select(column, Group, value) %>%
  spread(column, value)

但是你最终会得到比你预期更多的列,所以也许你可以给我们预期的输出(如 cmets 中所述)。

编辑: 要获得每人 8 列,请使用:

result <- test_data %>% mutate(person = row.names(test_data)) %>% 
  gather(key, value, -Group, -person) %>%
  group_by(Group, person) %>%
  mutate(column = paste0(person,'_',row_number(key))) %>%
  ungroup() %>%
  select(column, Group, value) %>%
  spread(column, value)

最后,如果您只想要 32 列而不关心哪个值来自哪个人可以使用:

result <- test_data %>% mutate(person = row.names(test_data)) %>% 
  gather(key, value, -Group, -person) %>%
  group_by(Group) %>% arrange(person, key) %>%
  mutate(column = row_number()) %>%
  ungroup() %>%
  select(column, Group, value) %>%
  spread(column, value)

要从数据框中删除 NA 值,请使用:

result[is.na(result)] <- 0

【讨论】:

  • 请看看我在akrun's答案下方的评论。
  • 最后一个正是我要找的!
【解决方案2】:
test_data$row <- row.names(test_data) 
data <- reshape(test_data, idvar= "Group", timevar = "row", direction = "wide")

它会给你一个长格式的数据。在编辑之前,这些列将按照您的需要命名。

【讨论】:

    【解决方案3】:

    或许我们也可以使用data.table

    library(data.table)
    dcast(melt(setDT(test_data, keep.rownames = TRUE), id.var= c("rn", "Group")), 
               Group~variable + rowid(variable), value.var = "value")
    

    更新

    dcast(melt(setDT(test_data, keep.rownames = TRUE), id.var= c("rn",
            "Group")), Group+rowid(variable) ~variable, value.var = "value")
    

    【讨论】:

    • 看看我的新编辑。是否可以使表格更窄?只需将值存储在彼此下方并将其扩展到最小值。在这种特定情况下,它将是 32 列。两行 32 列全是数字,一行 24 个值和 8 次 NA 在表的末尾。
    • @ShaxiLiver 我更新了帖子,但我不确定这是否是你想要的结构
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2023-01-30
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2020-09-25
    相关资源
    最近更新 更多