我正在尝试提出一种优雅的、基于规则的方法,根据列中的值组合为数据框中的行分配代码,使用以下数据:
library(tidyr)
df <- crossing(yr2018=c("M","S","W"),
yr2019=c("M","S","W"),
yr2020=c("M","S","W")) %>%
print(n=27)
# A tibble: 27 × 3
yr2018 yr2019 yr2020
<chr> <chr> <chr>
1 M M M
2 M M S
3 M M W
4 M S M
5 M S S
6 M S W
7 M W M
8 M W S
9 M W W
10 S M M
11 S M S
12 S M W
13 S S M
14 S S S
15 S S W
16 S W M
17 S W S
18 S W W
19 W M M
20 W M S
21 W M W
22 W S M
23 W S S
24 W S W
25 W W M
26 W W S
27 W W W
>
字符串
最后我想得到的是一个列,其中包含应用了如下规则的代码:
- 如果yr 2018、yr 2019和yr 2020中的所有3个值都相同(MMM、SSS或WWW),则将新列值设置为“CON”和任何唯一值的级联,因此“CONM”、“CONNS”或“CONW”。
- 如果第一列和第三列相同,但第二列不同,则根据行中的哪两个唯一值,将这两个唯一值按该顺序连接在一起,而不管列中的值的顺序如何。
- 如果所有三种都不同,无论顺序如何,那么“MSW”
- 如果最后两个值相同,但与第一个值不同,则将“CON”与最后一个值连接,因此可以是“CONM”、“CONS”或“CONW”
- 最后,如果前两个相同而最后一个不同,则将“CON”与第一列连接,因此可以是“CONM”、“CONS”或“CONW”
这感觉像是一个很大的、丑陋的if
语句,但我希望它更优雅,特别是因为我的真实的数据实际上是4x 5(625行)。它也感觉像是正则表达式,我很纠结。
我开始研究行函数,发现rowwise()
作为逻辑重新配置 Dataframe 的起点,但看起来可以以这种方式操作的函数数量有限。
欢迎各位指导!
4条答案
按热度按时间rur96b6h1#
您可以使用
mutate
和case_when
有效地满足这些条件。第二个逻辑中的sort
将按照您描述的方式组织字母。因为
case_when
迭代计算,所以你可以解析它,使它更优雅,但正如你所写的,它应该遵循你的确切条件:字符串
输出量:
型
mwkjh3gx2#
可以使用
str_replace
:字符串
你也可以使用
gsubfn::gsubfn
:型
zy1mlcev3#
一种方法可以是使用
rle
,如果有连续的粘贴到CON
,否则对唯一值进行排序。字符串
vngu2lb84#
对于较大的 Dataframe ,这可能是一个更好的解决方案,因为我们可以微调每个规则,除了已经发布的
case_when
和str_replace
答案之外。gather()
方法可以将数据框转换为具有3列的较长格式,并添加“年份”和“值”。然后,我们可以使用rowwise
对每行应用条件。这5条规则适用于case_when基于我们的新列year和value。然后ungroup()
数据恢复到原始形式。字符串