我有30万个人(身份证)的面板数据。每个ID每年都有1行(2013-2016年)。基于“代码”,确定“名称”的状态(每年)。但是,仍然存在一些错误。如果数据框中的一个ID在特定年份具有特定名称,则我想给每个人提供相同的代码和年份,也要为该名称提供相同的代码和年份。如果没有人在“名称”中有特定代码和年份的名称,则NA就足够了。这有点棘手,因为ID可以在多年内(而不是一年内)使用Codes进行切换。
例如:对于ID#2,2014年的名称应从NA更改为PIZZA,原因是数据框中的另一个ID(此处为#1)的相同ID和Year具有“ PIZZA”。但是,ID#3和ID#4在2016年都保持不变,因为没有人用代码05/1234和2016年在数据框中有名称。
> str(Poging23)
tibble [16 x 5] (S3: tbl_df/tbl/data.frame)
$ ID : num [1:16] 1 1 1 1 2 2 2 2 3 3 ...
$ Date_of_birth: POSIXct[1:16], format: "2000-05-25" "2000-05-25" "2000-05-25" "2000-05-25" ...
$ Code : chr [1:16] "01/1234" "01/1234" "01/1234" "01/1234" ...
$ Year : num [1:16] 2013 2014 2015 2016 2013 ...
$ Name : chr [1:16] "PIZZA" "PIZZA" "NA" "NA" ...
> dput(Poging23)
structure(list(ID = c(1, 1, 1, 1, 2, 2, 2, 2, 3, 3, 3, 3, 4,
4, 4, 4), Date_of_birth = structure(c(959212800, 959212800, 959212800,
959212800, 25315200, 25315200, 25315200, 25315200, 277862400,
277862400, 277862400, 277862400, 1267574400, 1267574400, 1267574400,
1267574400), class = c("POSIXct", "POSIXt"), tzone = "UTC"),
Code = c("01/1234", "01/1234", "01/1234", "01/1234", "01/1234",
"01/1234", "01/1234", "01/1234", "01/1234", "01/1234", "05/1234",
"05/1234", "05/1234", "05/1234", "05/1234", "05/1234"), Year = c(2013,
2014, 2015, 2016, 2013, 2014, 2015, 2016, 2013, 2014, 2015,
2016, 2013, 2014, 2015, 2016), Name = c("PIZZA", "PIZZA",
"NA", "NA", "NA", "NA", "PIZZA", "NA", "NA", "PIZZA", "NA",
"NA", "PASTA", "PASTA", "PASTA", "NA")), row.names = c(NA,
-16L), class = c("tbl_df", "tbl", "data.frame"))
不幸的是,这些代码无法正常工作(多年来没有考虑代码的更改):如何根据R中其他ID的单元格值/特征将ID的NA更改为字符值? / p>
编辑:我将NA命名为“ NA”,因为我首先在Excel中进行了预览。
也可以将所有名称更改为1,如果更容易将NA更改为0。
希望有人可以帮助我/给出提示!
谢谢!
答案 0 :(得分:1)
按代码和年份的功能汇总名称将显示每对因素的名称。对于每对,您可以查看是否至少存在一个名称
aggregate(Name ~ Year + Code, dfx, function(x) {x[x != "NA"]})
Year Code Name
1 2013 01/1234 PIZZA
2 2014 01/1234 PIZZA, PIZZA
3 2015 01/1234 PIZZA
4 2016 01/1234
5 2013 05/1234 PASTA
6 2014 05/1234 PASTA
7 2015 05/1234 PASTA
8 2016 05/1234
我将假设每对Year,Code必须始终具有相同的名称(可以在第2行中重复),并且只需要第一个
uu <- aggregate(Name ~ Year + Code, dfx, function(x) {x[x != "NA"][1]})
> uu
Year Code Name
1 2013 01/1234 PIZZA
2 2014 01/1234 PIZZA
3 2015 01/1234 PIZZA
4 2016 01/1234 <NA>
5 2013 05/1234 PASTA
6 2014 05/1234 PASTA
7 2015 05/1234 PASTA
8 2016 05/1234 <NA>
然后为dfx中匹配 uu 的每一行,可以从uu $ Name
中分配相应的名称。for (i in 1:nrow(uu)) {
dfx[
dfx$Name=="NA"
& dfx$Code == uu[i, "Code"]
& dfx$Year == uu[i, "Year"] , "Name" ] <- uu[i, "Name"]
}
> dfx
ID Date_of_birth Code Year Name
1 1 2000-05-25 01/1234 2013 PIZZA
2 1 2000-05-25 01/1234 2014 PIZZA
3 1 2000-05-25 01/1234 2015 PIZZA
4 1 2000-05-25 01/1234 2016 <NA>
5 2 1970-10-21 01/1234 2013 PIZZA
6 2 1970-10-21 01/1234 2014 PIZZA
7 2 1970-10-21 01/1234 2015 PIZZA
8 2 1970-10-21 01/1234 2016 <NA>
9 3 1978-10-22 01/1234 2013 PIZZA
10 3 1978-10-22 01/1234 2014 PIZZA
11 3 1978-10-22 05/1234 2015 PASTA
12 3 1978-10-22 05/1234 2016 <NA>
13 4 2010-03-03 05/1234 2013 PASTA
14 4 2010-03-03 05/1234 2014 PASTA
15 4 2010-03-03 05/1234 2015 PASTA
16 4 2010-03-03 05/1234 2016 <NA>
答案 1 :(得分:1)
在tidyverse
宇宙中可能的解决方案可以如下进行。我将过程分为几步,以便更清晰易懂。
首先,我们创建一个查找表,其中包含Code
和Year
的每种组合,Name
中与"NA"
library(tidyverse)
lookup <- Poging23 %>%
group_by(Code, Year) %>%
group_modify(~unique(.$Name) %>% enframe(name = NULL, value = "Name")) %>%
filter(Name != "NA")
# A tibble: 6 x 3
# Groups: Code, Year [6]
# Code Year Name
# <chr> <dbl> <chr>
# 1 01/1234 2013 PIZZA
# 2 01/1234 2014 PIZZA
# 3 01/1234 2015 PIZZA
# 4 05/1234 2013 PASTA
# 5 05/1234 2014 PASTA
# 6 05/1234 2015 PASTA
然后,我们在原始数据集和此查询表之间使用左联接
Poging23 %>%
select(-Name) %>%
left_join(lookup, by = c("Code", "Year"))
最终输出应符合您的预期
# A tibble: 16 x 5
# ID Date_of_birth Code Year Name
# <dbl> <dttm> <chr> <dbl> <chr>
# 1 1 2000-05-25 00:00:00 01/1234 2013 PIZZA
# 2 1 2000-05-25 00:00:00 01/1234 2014 PIZZA
# 3 1 2000-05-25 00:00:00 01/1234 2015 PIZZA
# 4 1 2000-05-25 00:00:00 01/1234 2016 NA
# 5 2 1970-10-21 00:00:00 01/1234 2013 PIZZA
# 6 2 1970-10-21 00:00:00 01/1234 2014 PIZZA
# 7 2 1970-10-21 00:00:00 01/1234 2015 PIZZA
# 8 2 1970-10-21 00:00:00 01/1234 2016 NA
# 9 3 1978-10-22 00:00:00 01/1234 2013 PIZZA
# 10 3 1978-10-22 00:00:00 01/1234 2014 PIZZA
# 11 3 1978-10-22 00:00:00 05/1234 2015 PASTA
# 12 3 1978-10-22 00:00:00 05/1234 2016 NA
# 13 4 2010-03-03 00:00:00 05/1234 2013 PASTA
# 14 4 2010-03-03 00:00:00 05/1234 2014 PASTA
# 15 4 2010-03-03 00:00:00 05/1234 2015 PASTA
# 16 4 2010-03-03 00:00:00 05/1234 2016 NA
如果要避免将过程分成较小的步骤,只需按以下步骤合并代码块
library(tidyverse)
Poging23 %>%
select(-Name) %>%
left_join(Poging23 %>%
group_by(Code, Year) %>%
group_modify(~unique(.$Name) %>% enframe(name = NULL, value = "Name")) %>%
filter(Name != "NA"),
by = c("Code", "Year"))