我有一个像下面这样的数据框,其中包含96,000行和不同数量的相同ID。我要选择具有相同ID的行,然后从日期最早的行中选择“销售额”。
ID Date1 Date2 Date3 Sales
------ ---------- ---------- ---------- -------
3351 7/18/18 1/8/2017 9/7/2016 $240
3351 9/15/14 $670
3351 4/5/2017 9/7/16
8222 6/6/2013 2/5/2008 $943
在这种情况下,对于ID 3351,我们会选择$ 670,因为第二个重复项中的Date2是在2014年。
for(i in length(data))
{
if(duplicated(dat17[i,1]) == TRUE)
{
pmin(dat17[1,7:9], dat17[2,7:9])
}
}
我正在尝试使用for循环来查找重复项并进行比较,但是我不确定如何使用重复项()函数给出的多行。 pmin()仅适用于矢量,我需要使用数据框中的数据。
答案 0 :(得分:4)
一种方法是使用dplyr
软件包,这会使这种事情变得更容易。
library(dplyr)
df <- read.table(text = "ID Date1 Date2 Date3 Sales
3351 7/18/18 1/8/2017 9/7/2016 $240
3351 NA 9/15/14 NA $670
3351 4/5/2017 9/7/16 NA NA
8222 NA 6/6/2013 2/5/2008 $943 ",
stringsAsFactors = FALSE,
header = TRUE) %>%
# make sure the date variables are in date format for sorting to work properly
mutate_at(vars(starts_with("Date")),lubridate::mdy)
df %>%
# calculate the minimum date for each row using pmin
mutate(min_date = pmin(Date1,Date2,Date3,na.rm = TRUE)) %>%
# arrange from lowest date to highest date
arrange(min_date) %>%
# for each ID
group_by(ID) %>%
# keep the first one
slice(1) %>%
# ungroup to allow future calculations
ungroup()
# A tibble: 2 x 6
# ID Date1 Date2 Date3 Sales min_date
# <int> <date> <date> <date> <chr> <date>
# 1 3351 NA 2014-09-15 NA $670 2014-09-15
# 2 8222 NA 2013-06-06 2008-02-05 $943 2008-02-05
答案 1 :(得分:1)
我们不需要将逻辑表达式与TRUE / FALSE进行比较。它已经是base R
中的逻辑输出(未使用外部软件包)
i1 <- !duplicated(dat17[[1]])
此外,在进行比较之前,请确保将“日期”列转换为Date
类
dat17[2:4] <- lapply(dat17[2:4], as.Date, format = "%m/%d/%y")
cbind(dat17[i1,], new = do.call(pmin, c(dat17[2:4][i1,], na.rm = TRUE)))
# ID Date1 Date2 Date3 Sales new
#1 3351 2018-07-18 2020-01-08 2020-09-07 $240 2018-07-18
#4 8222 <NA> 2020-06-06 2020-02-05 $943 2020-02-05
请注意,for
循环仅循环通过一个值length(data)
返回单个元素。另外,当下一行应为“ dat17”时,不确定此处的“数据”是什么
dat17 <- structure(list(ID = c(3351L, 3351L, 3351L, 8222L), Date1 = c("7/18/18",
NA, "4/5/2017", NA), Date2 = c("1/8/2017", "9/15/14", "9/7/16",
"6/6/2013"), Date3 = c("9/7/2016", NA, NA, "2/5/2008"), Sales = c("$240",
"$670", NA, "$943")), class = "data.frame", row.names = c(NA,
-4L))
答案 2 :(得分:1)
这里是一个选择:
library(tidyverse)
library(lubridate)
df <-
tibble(
id = c(3351, 3351, 8222, 8222),
date1 = c("2018-07-18", NA_character_, "2017-01-03", "2016-03-02"),
date2 = c("2016-03-04", "2015-03-02", NA_character_, "2017-04-05"),
sales = c(240, 670, NA_integer_, 300)
)
df
# A tibble: 4 x 4
id date1 date2 sales
<dbl> <chr> <chr> <dbl>
1 3351 2018-07-18 2016-03-04 240
2 3351 NA 2015-03-02 670
3 8222 2017-01-03 NA NA
4 8222 2016-03-02 2017-04-05 300
第一步是将各种日期列收集到一个列中:
df %>%
gather(key = date_col, value = date, date1:date2)
# A tibble: 8 x 4
id sales date_col date
<dbl> <dbl> <chr> <chr>
1 3351 240 date1 2018-07-18
2 3351 670 date1 NA
3 8222 NA date1 2017-01-03
4 8222 300 date1 2016-03-02
5 3351 240 date2 2016-03-04
6 3351 670 date2 2015-03-02
7 8222 NA date2 NA
8 8222 300 date2 2017-04-05
然后,您可以按ID分组并进行过滤以查找最早的日期。
df %>%
gather(key = date_col, value = date, date1:date2) %>%
filter(!is.na(date), !is.na(sales)) %>%
mutate(date = ymd(date)) %>%
group_by(id) %>%
filter(date == min(date)) %>%
ungroup()
# A tibble: 2 x 4
id sales date_col date
<dbl> <dbl> <chr> <date>
1 8222 300 date1 2016-03-02
2 3351 670 date2 2015-03-02