【问题标题】:Summing columns based on criteria根据条件对列求和
【发布时间】:2021-01-25 08:04:09
【问题描述】:

我有一个由三列组成的数据框:x、ID 和 date_time。 “x”列是变量 x 的记录,ID 表示正在记录的内容,而 date_time 表示何时记录。请参阅下面的数据框。

我想从这个数据帧计算一个新的数据帧,它有七列:“Measurement”、“ID”和“Date”、“x_4_10_day”、“Day_total”、“x_4_10_night”、“Night_total”。

  1. “测量”。此列应说明这是给定 ID 的数字测量值。测量从 23:00:00 开始,然后一直运行到第二天的 22:59:59。然而,测量在随机时间开始,因此第一次测量的持续时间不是 24 小时。最后一次测量也不是 24 小时。
  2. “身份证”。指明给定测量的 ID
  3. “日期”。此列应显示给定测量中最后一次记录的日期,格式为:yyyy.mm.dd。
  4. “x_4_10_day”:测量分为一天(7:00:00-22:59:59)和夜晚(23:00:00-6:59:59)。此列应指示在给定测量中每天 x 已在 4-10(均包括在内)之间的总时间量(以分钟为单位)。 x 在 4-10 之间的记录可以视为 x 在 4-10 之间持续 5 分钟,因为每次记录之间有 5 分钟。
  5. “Day_total”:此列应表示一天中测量的总时间(以分钟为单位)x。 x 中存在应减去的缺失值。 x 的缺失值留空。对于每个缺失的测量,应从总时间中减去 5 分钟。此外,一些测量在 7:00 之后开始。
  6. “x_4_10_night”:此列应表示在给定测量中每晚 x 的总时间(以分钟为单位)在 4 到 10 之间(均包括在内)。
  7. “Night_total”:此列应指示在一个晚上测量的总时间量(以分钟为单位)x。 x 中存在应减去的缺失值。 x 的缺失值留空。对于每个缺失的测量,应从总时间中减去 5 分钟。

每个唯一测量值都应该有一行。到目前为止,我有一个代码可以正确返回列:“Measurement”、“ID”和“Date”:

df1$mydate = as.Date(df1$date_time, format = "%Y.%m.%d %H:%M:%S")
df1$tm <- as.numeric(df1$date_time)
df1$dts <- 86400*as.numeric(df1$mydate)
df2 <- df1 %>% 
group_by(ID,mydate) %>% 
transform(date = case_when(((dts-3600)<tm & tm<(dts+82800)) ~paste0(mydate), ((dts+82800)<=tm) ~paste0(mydate+1) )) %>% 
select(ID,date) %>%   
unique() %>% 
group_by(ID) %>% 
mutate(measurement = row_number())

但是我不知道怎么做最后一个。

这是一个预期的输出:

dummy_output <- read.table(header=TRUE, text ="
                     ID Date        Measurement x_4_10_day Day_total x_4_10_night Night_total
                     12 2020.03.02  1           30         40        0            0
                     12 2020.03.03  2           0          0         45           75
                     13 2020.05.09  1           90         90        0            0
") 

非常感谢任何建议,谢谢!

这是数据:

structure(list(date_time = c("2020.03.02 22:00:17", "2020.03.02 22:05:17", 
"2020.03.02 22:10:17", "2020.03.02 22:35:17", "2020.03.02 22:40:17", 
"2020.03.02 22:45:17", "2020.03.02 22:50:17", "2020.03.02 22:55:17", 
"2020.03.02 23:00:17", "2020.03.02 23:05:17", "2020.03.02 23:10:17", 
"2020.03.02 23:15:17", "2020.03.02 23:20:17", "2020.03.02 23:25:17", 
"2020.03.02 23:30:17", "2020.03.02 23:35:17", "2020.03.02 23:40:17", 
"2020.03.02 23:45:17", "2020.03.02 23:50:17", "2020.03.02 23:55:17", 
"2020.03.03 00:00:17", "2020.03.03 00:55:17", "2020.03.03 01:00:17", 
"2020.03.03 01:05:17", "2020.03.03 01:10:17", "2020.03.03 01:15:17", 
"2020.03.03 01:20:17", "2020.03.03 01:25:17", "2020.05.09 08:39:32", 
"2020.05.09 08:39:32", "2020.05.09 08:39:32", "2020.05.09 08:39:32", 
"2020.05.09 08:39:32", "2020.05.09 08:39:32", "2020.05.09 08:39:32", 
"2020.05.09 08:39:32", "2020.05.09 08:39:32", "2020.05.09 08:39:32", 
"2020.05.09 08:39:32", "2020.05.09 08:39:32", "2020.05.09 08:39:32", 
"2020.05.09 08:39:32", "2020.05.09 08:39:32", "2020.05.09 08:39:32", 
"2020.05.09 08:39:32", "2020.05.09 08:39:32"), id = c(12L, 12L, 
12L, 12L, 12L, 12L, 12L, 12L, 12L, 12L, 12L, 12L, 12L, 12L, 12L, 
12L, 12L, 12L, 12L, 12L, 12L, 12L, 12L, 12L, 12L, 12L, 12L, 12L, 
13L, 13L, 13L, 13L, 13L, 13L, 13L, 13L, 13L, 13L, 13L, 13L, 13L, 
13L, 13L, 13L, 13L, 13L), x = c("7.55", "4.55", "4.55", "12", 
"12", "10", "10", "4.3", "", "", "4.3", "4.3", "4.3", "", "4.3", 
"12", "12", "12", "2", "12", "12", "", "8", "3", "3", "2", "2", 
"", "12", "10", "10", "4.3", "4.3", "4.3", "4.3", "4.3", "4.3", 
"4.3", "4.3", "12", "12", "12", "12", "12", "12", "12")), row.names = c(NA, 
46L), class = "data.frame")

【问题讨论】:

  • 是的,当然!感谢您让我知道我忘记了。
  • @Magnus,通过提供的示例数据,我无法理解x 是什么?
  • 所以!你的意思是你的第4列会有第一个值和最后一个值的时间差,以分钟为单位,基于两个条件1.给定值之间的X和2.时间应该是一天?我说的对吗?
  • 另外,col x 中的缺失值是什么意思?你的意思是NA
  • 再告诉我一件事,你能x 在任何一个白天/晚上不止一次地在 4 到 10 之间变化吗?就像它可能超过 10 然后回到范围内,并且可能再次增加或减少超出限制。

标签: r tidyverse


【解决方案1】:

我已将 id=14 添加到您的数据框中,其中只有夜间值。也许这就是您正在寻找的。请注意,您的预期值不完全符合您的要求。

df11 <- structure(list(date_time = c("2020.03.02 22:00:17", "2020.03.02 22:05:17", 
                             "2020.03.02 22:10:17", "2020.03.02 22:35:17", "2020.03.02 22:40:17", 
                             "2020.03.02 22:45:17", "2020.03.02 22:50:17", "2020.03.02 22:55:17", 
                             "2020.03.02 23:00:17", "2020.03.02 23:05:17", "2020.03.02 23:10:17", 
                             "2020.03.02 23:15:17", "2020.03.02 23:20:17", "2020.03.02 23:25:17", 
                             "2020.03.02 23:30:17", "2020.03.02 23:35:17", "2020.03.02 23:40:17", 
                             "2020.03.02 23:45:17", "2020.03.02 23:50:17", "2020.03.02 23:55:17", 
                             "2020.03.03 00:00:17", "2020.03.03 00:55:17", "2020.03.03 01:00:17", 
                             "2020.03.03 01:05:17", "2020.03.03 01:10:17", "2020.03.03 01:15:17", 
                             "2020.03.03 01:20:17", "2020.03.03 01:25:17", "2020.05.09 08:39:32", 
                             "2020.05.09 08:39:32", "2020.05.09 08:39:32", "2020.05.09 08:39:32", 
                             "2020.05.09 08:39:32", "2020.05.09 08:39:32", "2020.05.09 08:39:32", 
                             "2020.05.09 08:39:32", "2020.05.09 08:39:32", "2020.05.09 08:39:32", 
                             "2020.05.09 08:39:32", "2020.05.09 08:39:32", "2020.05.09 08:39:32", 
                             "2020.05.09 08:39:32", "2020.05.09 08:39:32", "2020.05.09 08:39:32", 
                             "2020.05.09 08:39:32", "2020.05.09 08:39:32", 
                             "2020.03.02 23:45:17", "2020.03.02 23:50:17", "2020.03.02 23:55:17", 
                             "2020.03.03 00:00:17", "2020.03.03 00:55:17", "2020.03.03 01:00:17" 
                             ), 
                      x = c("7.55", "4.55", "4.55", "12", 
                            "12", "10", "10", "4.3", "", "", "4.3", "4.3", "4.3", "", "4.3", 
                            "12", "12", "12", "2", "12", "12", "", "8", "3", "3", "2", "2", 
                            "", "12", "10", "10", "4.3", "4.3", "4.3", "4.3", "4.3", "4.3", 
                            "4.3", "4.3", "12", "12", "12", "12", "12", "12", "12",
                            "12", "10", "10", "4.3", "4.3", "4.3"),
               id = c(12L, 12L, 
                      12L, 12L, 12L, 12L, 12L, 12L, 12L, 12L, 12L, 12L, 12L, 12L, 12L, 
                      12L, 12L, 12L, 12L, 12L, 12L, 12L, 12L, 12L, 12L, 12L, 12L, 12L, 
                      13L, 13L, 13L, 13L, 13L, 13L, 13L, 13L, 13L, 13L, 13L, 13L, 13L, 
                      13L, 13L, 13L, 13L, 13L, 14L, 14L, 14L, 14L, 14L, 14L)), 
               row.names = c(NA, 52L), class = "data.frame")

df11$xn <- as.numeric(df11$x)
df1 <- df11 %>% transform(xmin = ifelse((xn<4 | xn>10 | is.na(xn)),0,5 ),
                          xmint = ifelse(is.na(xn),-5,5 ))
df1$dateTime = as_datetime(df1$date_time, format = "%Y.%m.%d %H:%M:%S")
df1$mydate = as.Date(df1$date_time, format = "%Y.%m.%d %H:%M:%S")

df1$tm <- as.numeric(df1$dateTime)
df1$dts <- 86400*as.numeric(df1$mydate)

df2 <- df1 %>% group_by(id,mydate) %>% 
         transform(date = case_when(((dts-3600)<tm & tm<(dts+82800) )~paste0(mydate),((dts+82800)<=tm)~paste0(mydate+1) )) %>%
         transform(dayrnight = ifelse((tm>=(dts+25200) & tm<(dts+82800) ),'day','night' ) ) %>% 
         group_by(id,date,dayrnight) %>% 
         dplyr::summarise(x_4_10 = sum(xmin), total = sum(xmint)) %>% 
         pivot_wider(id_cols = c(id,date), names_from = dayrnight, values_from = c("x_4_10", "total")) %>% 
         mutate_if(is.numeric , replace_na, replace = 0) %>% 
         group_by(id) %>% mutate(measurement = row_number()) %>% 
         select(id,date,measurement,x_4_10_day,total_day,x_4_10_night,total_night)

> df2
# A tibble: 4 x 7
# Groups:   id [3]
     id date       measurement x_4_10_day total_day x_4_10_night total_night
  <int> <chr>            <int>      <dbl>     <dbl>        <dbl>       <dbl>
1    12 2020-03-02           1         30        40            0           0
2    12 2020-03-03           2          0         0           25          50
3    13 2020-05-09           1         50        90            0           0
4    14 2020-03-03           1          0         0           25          30

【讨论】:

  • 在每 5 分钟进行一次测量的情况下,该解决方案是正确的。但这些是 Magnus 指定的随机时间。
  • @YBS,我认为代码运行良好。只需要仔细检查我的更多数据。但是,我已将“xmint = ifelse(is.na(xn),-5,5 ))”更改为“xmint = ifelse(is.na(xn),0,5 ))”。非常感谢您的帮助!
【解决方案2】:

我花了一些时间,但可能你想要这个

样本数据(由于13 中的日期/时间都相同

df <- structure(list(date_time = c("2020.03.02 22:00:17", "2020.03.02 22:05:17", 
                             "2020.03.02 22:10:17", "2020.03.02 22:35:17", "2020.03.02 22:40:17", 
                             "2020.03.02 22:45:17", "2020.03.02 22:50:17", "2020.03.02 22:55:17", 
                             "2020.03.02 23:00:17", "2020.03.02 23:05:17", "2020.03.02 23:10:17", 
                             "2020.03.02 23:15:17", "2020.03.02 23:20:17", "2020.03.02 23:25:17", 
                             "2020.03.02 23:30:17", "2020.03.02 23:35:17", "2020.03.02 23:40:17", 
                             "2020.03.02 23:45:17", "2020.03.02 23:50:17", "2020.03.02 23:55:17", 
                             "2020.03.03 00:00:17", "2020.03.03 00:55:17", "2020.03.03 01:00:17", 
                             "2020.03.03 01:05:17", "2020.03.03 01:10:17", "2020.03.03 01:15:17", 
                             "2020.03.03 01:20:17", "2020.03.03 01:25:17", "2020.05.09 08:39:32", 
                             "2020.05.09 08:44:32", "2020.05.09 08:49:32", "2020.05.09 08:54:32", 
                             "2020.05.09 08:59:32", "2020.05.09 09:39:32", "2020.05.09 09:44:32", 
                             "2020.05.09 09:49:32", "2020.05.09 09:59:32", "2020.05.09 10:39:32", 
                             "2020.05.09 11:39:32", "2020.05.09 12:39:32", "2020.05.09 13:39:32", 
                             "2020.05.09 14:39:32", "2020.05.09 15:39:32", "2020.05.09 16:39:32", 
                             "2020.05.09 17:39:32", "2020.05.09 18:39:32"), id = c(12L, 12L, 
                                                                                   12L, 12L, 12L, 12L, 12L, 12L, 12L, 12L, 12L, 12L, 12L, 12L, 12L, 
                                                                                   12L, 12L, 12L, 12L, 12L, 12L, 12L, 12L, 12L, 12L, 12L, 12L, 12L, 
                                                                                   13L, 13L, 13L, 13L, 13L, 13L, 13L, 13L, 13L, 13L, 13L, 13L, 13L, 
                                                                                   13L, 13L, 13L, 13L, 13L), x = c("7.55", "4.55", "4.55", "12", 
                                                                                                                   "12", "10", "10", "4.3", "", "", "4.3", "4.3", "4.3", "", "4.3", 
                                                                                                                   "12", "12", "12", "2", "12", "12", "", "8", "3", "3", "2", "2", 
                                                                                                                   "", "12", "10", "10", "4.3", "4.3", "4.3", "4.3", "4.3", "4.3", 
                                                                                                                   "4.3", "4.3", "12", "12", "12", "12", "12", "12", "12")), row.names = c(NA, 
                                                                                                                                                                                           46L), class = "data.frame")

编辑结果

library(tidyverse)
library(lubridate)

df %>% as_tibble() %>%
  transform(x = as.numeric(x), 
            date_time = as_datetime(date_time),
            id = as.character(id)) %>%
  mutate(d_n = ifelse(hour(date_time)>=7 & hour(date_time)<23, 'day', 'night'),
         Date = as.Date(date_time, format = "%Y.%m.%d %H:%M:%S"),
         valid_m = ifelse(x>=4 & x<= 10, 1, 0)) %>%
  mutate(valid_m = ifelse(is.na(valid_m), 0, valid_m)) %>% #valid measurements
  arrange(id, date_time) %>%
  group_by(id) %>%
  mutate(validm_d = as.numeric(lead(date_time)-date_time)) %>%
  filter(!is.na(validm_d)) %>%
  group_by(id, Date, d_n, valid_m) %>%
  summarise(x_tm = sum(validm_d)) %>%
  ungroup() %>%
  pivot_wider(names_from = d_n, values_from = x_tm, values_fill =0) %>%
  group_by(id, Date) %>%
  mutate(day_t = sum(day), night_t = sum(night)) %>% 
  filter(valid_m != 0) %>%
  group_by(id) %>%
  mutate(measurement = row_number()) %>%
  select(id, measurement, Date, x_4_10_day =day, x_4_10_total =day_t, 
         x_4_10_night =night, x_4_10_totaln = night_t)

desired_result

id    measurement Date       x_4_10_day x_4_10_total x_4_10_night x_4_10_totaln
  <chr>       <int> <date>          <dbl>        <dbl>        <dbl>         <dbl>
1 12              1 2020-03-02         50           60           20            60
2 12              2 2020-03-03          0            0            5            85
3 13              1 2020-05-09        235          600            0             0

在此解决方案中,我删除了每次测量的最后一个值,因为我不确定该测量需要多长时间。您可以适当地更改代码。基本上“天”的最后一次测量结束了 2300 小时,因此第一行的结果应该比显示的少 17 秒。

【讨论】:

  • 感谢您的帮助,非常感谢。当我使用您的代码时,我没有得到 x_4_10_day、Day_total、x_4_10_night 和 Night_total 的正确结果。数字太高了。
  • hm,使用您提供的数据和代码,我在 "x_4_10_day" 列的第一行得到 60。应该是 40...
  • 在您现在提供的数据和代码中,第一行的“x_4_10_day”列是50,“x_4_10_total”列是60。然而,它们应该是 30 和 40。在测量 1 中,在 4 和 10 之间有 6 个 x 记录,总共有 8 个记录(在 7:00:00 和 22:59:59 之间)。
  • @Magnus 现在它在第一行 (5,5,25,5,5,5) 中分别为 (1,2,3,6,7,8th) 值给出 50 作为时差三读和四读之间为 25 分钟
  • @Magnus,请重新检查。
猜你喜欢
  • 2021-10-12
  • 1970-01-01
  • 1970-01-01
  • 2021-05-12
  • 2021-05-05
  • 2016-09-17
  • 1970-01-01
  • 2013-12-03
相关资源
最近更新 更多