在 R 中分隔大型数据帧,每列中有多个整数,然后对整数求和



>我在 R 中有一个数据帧,我从一个文本文件中读入它,该文件包含两列,每列每个值有多个整数。我需要从一列(开始(中减去另一列(结束(中的相应整数的相应整数。最后一步,我最终想要得到的是将所有距离相加,以获得每条轨道的总距离。下面的数据帧只是一个示例,但有问题的数据帧每列大约有 20 个整数,并且有几十个轨道(行(。

轨道 A: (15-6(+(20-5(+(7-1(

track     StartDist         EndDist
A         1, 5, 6           7, 20, 15
B         1, 7, 8, 11       6, 21, 22, 25

我会使用 separate() 函数,但每列的整数数量不相等。我还考虑过重新制作数据帧,每行只包含一个整数,但我最终会得到成千上万行,然后必须再次将它们组合回来以计算每个轨道的总数。有什么建议吗?

下面是一个基本的 R 解决方案。我们使用splittrack对条目进行分组,然后使用自定义函数splt将条目拆分为列StartDist,并按", " EndDist;然后我们使用 mapply 计算成对差异,并返回第 sum.diff 列中所有成对距离的总和。

splt <- function(x) as.numeric(unlist(strsplit(as.character(x), ", ")))
df$sum.diff = sapply(split(df, df$track), function(x) {
    start <- splt(x$StartDist);
    end <- splt(x$EndDist);
    sum(mapply(function(a, b) b - a, start, end)) });
df;
#  track   StartDist       EndDist sum.diff
#1     A     1, 5, 6     7, 20, 15       30
#2     B 1, 7, 8, 11 6, 21, 22, 25       47

示例数据

df <- read.table(text =
    "track     StartDist         EndDist
A         '1, 5, 6'           '7, 20, 15'
B         '1, 7, 8, 11'       '6, 21, 22, 25'", header = T)

我真的建议将其存储为"长"文件,以使任何后续分析变得更加简单。如果你在整洁的世界里,我会做这样的事情:

library(tidyverse)
datlong <- dat %>%
  mutate_at(vars(StartDist, EndDist), str_split, ",\s+") %>%
  unnest %>% 
  mutate_at(vars(StartDist, EndDist), as.numeric) 
datlong %>%
  group_by(track) %>%
  summarise(Len = sum(EndDist - StartDist))
# A tibble: 2 x 2
#  track   Len
#  <chr> <dbl>
#1     A    30
#2     B    47

dat在哪里:

txt <- "track|StartDist|EndDist
A|1, 5, 6|7, 20, 15
B|1, 7, 8, 11|6, 21, 22, 25"
dat <- read.table(text=txt, sep="|", header=TRUE, stringsAsFactors=FALSE)

以及用于娱乐和游戏的基本 R 翻译:

vars    <- c("StartDist", "EndDist")
othvars <- setdiff(names(dat), vars)
dat[vars] <- lapply(dat[vars], strsplit, ",\s+")
datlong <- cbind(
  dat[othvars][rep(seq_len(nrow(dat)), lengths(dat[[vars[1]]])),, drop=FALSE],
  lapply(dat[vars], unlist),
  stringsAsFactors=FALSE
)
datlong[vars] <- lapply(datlong[vars], as.numeric)
aggregate(cbind(Len = EndDist - StartDist) ~ track, data=datlong, FUN=sum)

这是一个dplyr解决方案,它也使用 stringr .我们使用 rowwise()mutate每一行应用以下操作: str_split()将每个"Dist"列中的字符串分隔为字母数字字符串列表,然后取消列出,强制转换为数字向量,并按您请求的顺序减去。然后将生成的数值向量的元素相加。

就其价值而言,我更喜欢基本R解决方案,因此我认为Maurits Evers的解决方案更优雅:

library(dplyr)
library(stringr)
track <- c("A", "B")
StartDist <- c("1, 5, 6", "1, 7, 8, 11")
EndDist <- c("7, 20, 15", "6, 21, 22, 25")
df <- data.frame(track,StartDist,EndDist)
df <- mutate(rowwise(df),
             sum = sum(as.numeric(unlist(str_split(EndDist, ","))) - as.numeric(unlist(str_split(StartDist, ",")))))

输出:

# A tibble: 2 x 4
  track StartDist   EndDist         sum
  <fct> <fct>       <fct>         <dbl>
1 A     1, 5, 6     7, 20, 15       30.
2 B     1, 7, 8, 11 6, 21, 22, 25   47.

相关内容

最新更新