R 将某一行的值与data.table中以前的所有行进行比较
我有一个数据集,包含涉及某类产品的公司。 数据集如下所示:R 将某一行的值与data.table中以前的所有行进行比较,r,group-by,data.table,grouping,R,Group By,Data.table,Grouping,我有一个数据集,包含涉及某类产品的公司。 数据集如下所示: df <- data.table(year=c(1979,1979,1980,1980,1980,1981,1981,1982,1982,1982,1982), category = c("A","A","B","C","A","D","C","F","F","A","B")) 我倾向于使用data.table,因为我有150多万个观察结果,并且希望能够通过公司ID分组来复制解决方案 非常感谢您
df <- data.table(year=c(1979,1979,1980,1980,1980,1981,1981,1982,1982,1982,1982),
category = c("A","A","B","C","A","D","C","F","F","A","B"))
我倾向于使用data.table,因为我有150多万个观察结果,并且希望能够通过公司ID分组来复制解决方案
非常感谢您的帮助,并提前向您表示感谢。我们可以为每个
类别指定第一年为“新”
library(data.table)
df[, Newness := c("NEW", "OLD")[(match(year, unique(year)) > 1) + 1], category]
df
# year category Newness
# 1: 1979 A NEW
# 2: 1979 A NEW
# 3: 1980 B NEW
# 4: 1980 C NEW
# 5: 1980 A OLD
# 6: 1981 D NEW
# 7: 1981 C OLD
# 8: 1982 F NEW
# 9: 1982 F NEW
#10: 1982 A OLD
#11: 1982 B OLD
类似地,在dplyr
中,这可以写成:
library(dplyr)
df %>%
group_by(category) %>%
mutate(Newness = c("NEW", "OLD")[(match(year, unique(year)) > 1) + 1])
您可以在基本R中使用duplicated+ifelse
:
transform(df,Newness = ifelse(duplicated(category)==duplicated(df),"New","Old"))
year category Newness
1: 1979 A New
2: 1979 A New
3: 1980 B New
4: 1980 C New
5: 1980 A Old
6: 1981 D New
7: 1981 C Old
8: 1982 F New
9: 1982 F New
10: 1982 A Old
11: 1982 B Old
在data.table中,您将执行以下操作:
library(data.table)
df[,Newness := ifelse(duplicated(.SD)==duplicated(category),"New","Old")]
df
year category Newness
1: 1979 A New
2: 1979 A New
3: 1980 B New
4: 1980 C New
5: 1980 A Old
6: 1981 D New
7: 1981 C Old
8: 1982 F New
9: 1982 F New
10: 1982 A Old
11: 1982 B Old
另一个数据表
选项:
df[, Newness := "OLD"][
unique(df, by="category"), on=.(year, category), Newness := "NEW"]
定时代码:
library(data.table)
set.seed(0L)
nr <- 1.5e6
df <- data.table(year=sample(1970:2019, nr, TRUE), category=sample(1e4, nr, TRUE))
setkey(df, year, category)
mtd0 <- function()
df[, Newness := c("NEW", "OLD")[(match(year, unique(year)) > 1) + 1], category]
mtd1 <- function()
df[, Newness := ifelse(duplicated(.SD)==duplicated(category),"New","Old")]
mtd2 <- function()
df[, Newness := "OLD"][
unique(df, by="category"), on=.(year, category), Newness := "NEW"]
microbenchmark::microbenchmark(times=3L,
mtd0(), mtd1(), mtd2())
您可以按以下方式解决问题:
# Method 1:
setDT(df, key = "year")[, Newness := fifelse(year == year[1L], "NEW", "OLD"), category]
# Method 2
setDT(df, key = "year")[, Newness := c("NEW", "OLD")[match(year, year[1L], 2)], category]
# year category Newness
# 1: 1979 A NEW
# 2: 1979 A NEW
# 3: 1980 B NEW
# 4: 1980 C NEW
# 5: 1980 A OLD
# 6: 1981 D NEW
# 7: 1981 C OLD
# 8: 1982 F NEW
# 9: 1982 F NEW
# 10: 1982 A OLD
# 11: 1982 B OLD
不是答案,但由于效率是一个问题,我想张贴不同方法之间的比较。这是在我正在研究的专利数据库上运行的
> Ronak <- function()
+ df[, Newness := c("NEW", "OLD")[(match(year, unique(year)) > 1) + 1], category]
> B._Christian1 <- function()
+ df[, Newness := fifelse(year == year[1L], "NEW", "OLD"), category]
> B._Christian2 <- function()
+ df[, Newness := c("NEW", "OLD")[match(year, year[1L], 2)], category]
> Onyambu <- function()
+ df[,Newness := ifelse(duplicated(.SD)==duplicated(category),"New","Old")]
> chinsoon12 <- function()
+ df[, Newness := "OLD"][unique(df, by="category"), on=.(year, category),
+ Newness := "NEW"]
>
> microbenchmark::microbenchmark(times=3L,
+ Ronak(), B._Christian1(), B._Christian2(), Onyambu(), chinsoon12())
Unit: milliseconds
expr min lq mean median uq max neval
Ronak() 482.6191 482.7456 484.3963 482.8720 485.2849 487.6977 3
B._Christian1() 240.3175 242.9452 243.9646 245.5729 245.7881 246.0033 3
B._Christian2() 274.8113 278.3835 279.7271 281.9557 282.1850 282.4142 3
Onyambu() 2374.6428 2377.0848 2379.3771 2379.5267 2381.7442 2383.9617 3
chinsoon12() 200.6551 200.8337 202.5799 201.0123 203.5423 206.0723 3
>Ronak 1)+1],类别]
>B."基督教1 B."基督教2 Onyanbu chinsoon12
>微基准::微基准(时间=3L,
+Ronak(),B._Christian1(),B._Christian2(),Onyanbu(),chinsoon12())
单位:毫秒
expr最小lq平均uq最大neval
Ronak()482.6191482.7456484.3963482.8720485.2849487.69773
B._Christian1()240.3175 242.9452 243.9646 245.5729 245.7881 246.0033 3
B._Christian2()274.8113 278.3835 279.7271 281.9557 282.1850 282.4142 3
Onyanbu()2374.6428 2377.0848 2379.3771 2379.5267 2381.7442 2383.9617 3
chinsoon12()200.6551 200.8337 202.5799 201.0123 203.5423 206.0723 3
再次感谢。我认为你的答案不对。您获得了预期产出,因为每个类别第一次出现在可复制数据中的时间实际上与公司进入该类别的第一年一致。不能保证整个数据集都是这样。如果更改行的顺序(例如,set.seed(2)
;df@B.ChristianKamgang如果数据没有排序,你总是可以对数据进行排序。是的,但只要没有指定数据是排序的,我认为你不应该假设它是排序的,如果你这样做,那么我认为你应该明确指定获得正确结果的必要性。@RonakShah不是无论如何,这里我可以限制在一个特定的时间段内?例如,我不会查看整个数据集,而是查找过去5年中匹配的数据集?我认为这不是一个简单/小的解决方案。也许,作为一个新问题来问吧?我认为你的答案不正确。你获得了预期的输出,因为每个类别第一次出现可复制数据中的s实际上与公司进入该类别的第一年一致。不能保证整个数据集都是如此。如果您更改行的顺序(例如set.seed(2));df@onyanbu我在上问了一个单独的相关问题,如果您对此有任何想法,我将不胜感激。我认为您的答案是不正确的。由于您生成的数据集中的第一年是1970年,我们预计变量Newness
的所有内容在1970年都是New
(没有上一年!)。如果您使用代码生成的输出将1970年的变量Newness
制成表格,您会发现某些实例的值为OLD
(但情况不应该如此,因为1970年没有旧类别!)。例如,mtd2()[year==1970,.N,Newness]
给出775个新输入和29103个旧输入!!此外,所有输出都不相同。如果在可复制数据集上应用代码,您可能会意外获得预期输出;但是,这是因为每个类别在可复制数据中出现的第一次时间实际上与出现的第一年一致一家公司就属于这一类,而且不能保证整个数据集都是这样。啊,我明白你的意思了。数据需要更新sorted@chinsoon12我是否可以限制在某个特定的时间段内?例如,我不需要查看整个数据集,而是要查找过去5年中匹配的数据集?@chinsoon12。谢谢你的帮助他回答。我在上一次会议上作为一个单独的问题问了这个问题。我是否可以限制在某个特定的时间段内?例如,我不需要查看整个数据集,而是要查找过去5年中匹配的数据?
# Method 1:
setDT(df, key = "year")[, Newness := fifelse(year == year[1L], "NEW", "OLD"), category]
# Method 2
setDT(df, key = "year")[, Newness := c("NEW", "OLD")[match(year, year[1L], 2)], category]
# year category Newness
# 1: 1979 A NEW
# 2: 1979 A NEW
# 3: 1980 B NEW
# 4: 1980 C NEW
# 5: 1980 A OLD
# 6: 1981 D NEW
# 7: 1981 C OLD
# 8: 1982 F NEW
# 9: 1982 F NEW
# 10: 1982 A OLD
# 11: 1982 B OLD
> Ronak <- function()
+ df[, Newness := c("NEW", "OLD")[(match(year, unique(year)) > 1) + 1], category]
> B._Christian1 <- function()
+ df[, Newness := fifelse(year == year[1L], "NEW", "OLD"), category]
> B._Christian2 <- function()
+ df[, Newness := c("NEW", "OLD")[match(year, year[1L], 2)], category]
> Onyambu <- function()
+ df[,Newness := ifelse(duplicated(.SD)==duplicated(category),"New","Old")]
> chinsoon12 <- function()
+ df[, Newness := "OLD"][unique(df, by="category"), on=.(year, category),
+ Newness := "NEW"]
>
> microbenchmark::microbenchmark(times=3L,
+ Ronak(), B._Christian1(), B._Christian2(), Onyambu(), chinsoon12())
Unit: milliseconds
expr min lq mean median uq max neval
Ronak() 482.6191 482.7456 484.3963 482.8720 485.2849 487.6977 3
B._Christian1() 240.3175 242.9452 243.9646 245.5729 245.7881 246.0033 3
B._Christian2() 274.8113 278.3835 279.7271 281.9557 282.1850 282.4142 3
Onyambu() 2374.6428 2377.0848 2379.3771 2379.5267 2381.7442 2383.9617 3
chinsoon12() 200.6551 200.8337 202.5799 201.0123 203.5423 206.0723 3