重新排序数据框中因子名称的级别
Reorder levels of factor names in data frame
我有一个 DF
,只有一列:DF$A
。这是我需要以特定方式重新排序的名称的一个因素:
l
pheno
l.ldl.a
m.ldl.b
s.ldl.c
x.vldl.b
l.vldl.c
m.vldl.d
s.vldl.f
xs.vldl.h
xxl.vldl.a
xl.hdl.a
l.hdl.b
m.hdl.c
s.hdl.d
我尝试根据两个
重新排序 DF$A
创建 column 2
reorderLevels <- c(XXL.VLDL,XL.VLDL,L.VLDL,M.VLDL,S.VLDL,XS.VLDL,
IDL,L.LDL,M.LDL,S.LDL,XL.HDL,L.HDL,M.HDL,S.HDL)
不关心名字的最后一部分。
我知道如何根据名称的第一部分(第一个点之前)或名称的第二部分(点之间的部分)重新排序,但我不知道如何根据名称的两个部分进行排列.
到目前为止,我可以使用以下命令重新排序,但只能根据名称的一部分
l1 <- l %>% mutate(m2 = match(sapply(strsplit(l$pheno, "[.]"),
function(x) x[1]), reorderLevels)) %>%
arrange(m2) %>%
select(-m2)
如果你想重新排序,比方说,第二部分然后是第一部分(它们已经先排序然后是第二部分),按重要性顺序传递 order
你关心的标签部分.你可以使用sub
来拉出碎片:
levels(DF$A) <- levels(DF$A)[order(sub('.*\.(.*)\..*', '\1', levels(DF$A)),
sub('\..*', '', levels(DF$A)))]
levels(DF$A)
# [1] "l.hdl.b" "m.hdl.c" "s.hdl.d" "xl.hdl.a" "l.ldl.a" "m.ldl.b" "s.ldl.c"
# [8] "l.vldl.c" "m.vldl.d" "s.vldl.f" "x.vldl.b" "xs.vldl.h" "xxl.vldl.a"
注意 hdl
排在前面,其中的顺序按第一部分排序。
我不是 100% 确定你在问什么。我 认为 你想根据以下方案对因子 DF$A
重新排序:
最高优先级:按中段排列,顺序如下:
middle.ordering = c('vldl', 'idl', 'ldl', 'hdl')
第二优先级:安排第一部分,顺序如下(我添加了一个'x',尽管它不在你的reoderLines
中,因为你有一个'x' 在 DF$A):
first.ordering = c('xxl', 'xl', 'l', 'm', 's', 'x', 'xs')
你不关心最后一节的顺序,但我只知道如果我们指定一个如何轻松解决这个问题,所以我选择了一个任意的字母顺序见最后一节:
last.ordering = c('a', 'b', 'c', 'd', 'f', 'h')
至于你最后的输出,我不知道你想要什么。我可以想到您可能想要的 4 种可能的东西:
DF$A
按照您编写的确切顺序,但按照您想要的顺序添加新级别。如果您绘制这些数据的图,这将很有用,因为这些图将根据因子水平排列。这也意味着,如果您在数据框中有其他列,则可以使所有行之间的配对保持相同。看起来像这样:
[1] l.ldl.a m.ldl.b s.ldl.c x.vldl.b l.vldl.c m.vldl.d s.vldl.f xs.vldl.h xxl.vldl.a xl.hdl.a l.hdl.b m.hdl.c
[13] s.hdl.d
Levels: xxl.vldl.a l.vldl.c m.vldl.d s.vldl.f x.vldl.b xs.vldl.h l.ldl.a m.ldl.b s.ldl.c xl.hdl.a l.hdl.b m.hdl.c s.hdl.d
DF$A
以新顺序排列,但具有与以前相同的按字母顺序排列的级别(例如,级别 1 对应于 l.hdl.b,因为这是 [=21 的第一个元素=] 按字母顺序)。看起来像这样:
[1] xxl.vldl.a l.vldl.c m.vldl.d s.vldl.f x.vldl.b xs.vldl.h l.ldl.a m.ldl.b s.ldl.c xl.hdl.a l.hdl.b m.hdl.c
[13] s.hdl.d
Levels: l.hdl.b l.ldl.a l.vldl.c m.hdl.c m.ldl.b m.vldl.d s.hdl.d s.ldl.c s.vldl.f xl.hdl.a xs.vldl.h x.vldl.b xxl.vldl.a
DF$A
新顺序,新等级。看起来像这样:
[1] xxl.vldl.a l.vldl.c m.vldl.d s.vldl.f x.vldl.b xs.vldl.h l.ldl.a m.ldl.b s.ldl.c xl.hdl.a l.hdl.b m.hdl.c
[13] s.hdl.d
Levels: xxl.vldl.a l.vldl.c m.vldl.d s.vldl.f x.vldl.b xs.vldl.h l.ldl.a m.ldl.b s.ldl.c xl.hdl.a l.hdl.b m.hdl.c s.hdl.d
您可能还想为 DF$A 中实际实现的因素设置更多可能的水平,例如如果您稍后要添加更多数据。如果是这样,那么您的输出将如下所示,这三个部分的所有可能顺序都包含在内:
[1] l.ldl.a m.ldl.b s.ldl.c x.vldl.b l.vldl.c m.vldl.d s.vldl.f xs.vldl.h xxl.vldl.a xl.hdl.a l.hdl.b m.hdl.c
[13] s.hdl.d
168 Levels: xxl.vldl.a xxl.vldl.b xxl.vldl.c xxl.vldl.d xxl.vldl.f xxl.vldl.h xl.vldl.a xl.vldl.b xl.vldl.c xl.vldl.d xl.vldl.f ... xs.hdl.h
如果其中一个是您想要的,那么这里有一种方法可以完成这些事情:
DF = data.frame(A=factor(c(
'l.ldl.a',
'm.ldl.b',
's.ldl.c',
'x.vldl.b',
'l.vldl.c',
'm.vldl.d',
's.vldl.f',
'xs.vldl.h',
'xxl.vldl.a',
'xl.hdl.a',
'l.hdl.b',
'm.hdl.c',
's.hdl.d')))
first.ordering = c('xxl', 'xl', 'l', 'm', 's', 'x', 'xs')
middle.ordering = c('vldl', 'idl', 'ldl', 'hdl')
last.ordering = c('a', 'b', 'c', 'd', 'f', 'h')
# make a big cartesion product of the orderings,
# making sure that the top-priority orderings are mentioned *last*
# in expand.gird
complete.ordering = with(
expand.grid(last.ordering, first.ordering, middle.ordering),
paste(Var2, Var3, Var1, sep='.'))
new.levels = complete.ordering[complete.ordering %in% DF$A]
A.with.new.levels.but.same.order = factor(DF$A, levels=new.levels)
A.with.new.order.but.same.levels = DF$A[order(as.numeric(A.with.new.levels.but.same.order))]
A.with.new.order.and.levels = factor(A.with.new.order.but.same.levels, levels=new.levels)
A.with.same.order.and.more.levels = factor(DF$A, levels=complete.ordering)
此外,如果您的原始数据框有更多列,例如它看起来像这样:
A another.column
1 l.ldl.a 1
2 m.ldl.b 2
3 s.ldl.c 3
4 x.vldl.b 4
5 l.vldl.c 5
6 m.vldl.d 6
7 s.vldl.f 7
8 xs.vldl.h 8
9 xxl.vldl.a 9
10 xl.hdl.a 10
11 l.hdl.b 11
12 m.hdl.c 12
13 s.hdl.d 13
并且您想将所有行的顺序重新排列在一起,保留每行元素之间的关联,那么您可以执行以下操作:
A.with.new.levels.but.same.order = factor(DF$A, levels=new.levels)
DF.with.new.order = DF[order(as.numeric(A.with.new.levels.but.same.order)),]
这将为您提供以下数据框:
A another.column
9 xxl.vldl.a 9
5 l.vldl.c 5
6 m.vldl.d 6
7 s.vldl.f 7
4 x.vldl.b 4
8 xs.vldl.h 8
1 l.ldl.a 1
2 m.ldl.b 2
3 s.ldl.c 3
10 xl.hdl.a 10
11 l.hdl.b 11
12 m.hdl.c 12
13 s.hdl.d 13
我想建议 tidyr
和 dplyr
作为替代方案。
DF %>%
separate("A", c("first", "middle", "last"), sep="[.]") %>%
arrange(middle, first) %>%
unite(A, c(first, middle,last), sep=".") %>%
mutate(A=as.factor(A))
首先我们把这三个部分分开,排列它们,然后合二为一。最后,我们按照新顺序重做关卡。
这给
A
1 l.hdl.b
2 m.hdl.c
3 s.hdl.d
4 xl.hdl.a
5 l.ldl.a
6 m.ldl.b
7 s.ldl.c
8 l.vldl.c
9 m.vldl.d
10 s.vldl.f
11 x.vldl.b
12 xs.vldl.h
13 xxl.vldl.a
比 levels
答案稍长,但可能更具可读性。
我有一个 DF
,只有一列:DF$A
。这是我需要以特定方式重新排序的名称的一个因素:
l
pheno
l.ldl.a
m.ldl.b
s.ldl.c
x.vldl.b
l.vldl.c
m.vldl.d
s.vldl.f
xs.vldl.h
xxl.vldl.a
xl.hdl.a
l.hdl.b
m.hdl.c
s.hdl.d
我尝试根据两个
重新排序DF$A
创建 column 2
reorderLevels <- c(XXL.VLDL,XL.VLDL,L.VLDL,M.VLDL,S.VLDL,XS.VLDL,
IDL,L.LDL,M.LDL,S.LDL,XL.HDL,L.HDL,M.HDL,S.HDL)
不关心名字的最后一部分。
我知道如何根据名称的第一部分(第一个点之前)或名称的第二部分(点之间的部分)重新排序,但我不知道如何根据名称的两个部分进行排列.
到目前为止,我可以使用以下命令重新排序,但只能根据名称的一部分
l1 <- l %>% mutate(m2 = match(sapply(strsplit(l$pheno, "[.]"),
function(x) x[1]), reorderLevels)) %>%
arrange(m2) %>%
select(-m2)
如果你想重新排序,比方说,第二部分然后是第一部分(它们已经先排序然后是第二部分),按重要性顺序传递 order
你关心的标签部分.你可以使用sub
来拉出碎片:
levels(DF$A) <- levels(DF$A)[order(sub('.*\.(.*)\..*', '\1', levels(DF$A)),
sub('\..*', '', levels(DF$A)))]
levels(DF$A)
# [1] "l.hdl.b" "m.hdl.c" "s.hdl.d" "xl.hdl.a" "l.ldl.a" "m.ldl.b" "s.ldl.c"
# [8] "l.vldl.c" "m.vldl.d" "s.vldl.f" "x.vldl.b" "xs.vldl.h" "xxl.vldl.a"
注意 hdl
排在前面,其中的顺序按第一部分排序。
我不是 100% 确定你在问什么。我 认为 你想根据以下方案对因子 DF$A
重新排序:
最高优先级:按中段排列,顺序如下:
middle.ordering = c('vldl', 'idl', 'ldl', 'hdl')
第二优先级:安排第一部分,顺序如下(我添加了一个'x',尽管它不在你的
reoderLines
中,因为你有一个'x' 在 DF$A):first.ordering = c('xxl', 'xl', 'l', 'm', 's', 'x', 'xs')
你不关心最后一节的顺序,但我只知道如果我们指定一个如何轻松解决这个问题,所以我选择了一个任意的字母顺序见最后一节:
last.ordering = c('a', 'b', 'c', 'd', 'f', 'h')
至于你最后的输出,我不知道你想要什么。我可以想到您可能想要的 4 种可能的东西:
DF$A
按照您编写的确切顺序,但按照您想要的顺序添加新级别。如果您绘制这些数据的图,这将很有用,因为这些图将根据因子水平排列。这也意味着,如果您在数据框中有其他列,则可以使所有行之间的配对保持相同。看起来像这样:[1] l.ldl.a m.ldl.b s.ldl.c x.vldl.b l.vldl.c m.vldl.d s.vldl.f xs.vldl.h xxl.vldl.a xl.hdl.a l.hdl.b m.hdl.c [13] s.hdl.d Levels: xxl.vldl.a l.vldl.c m.vldl.d s.vldl.f x.vldl.b xs.vldl.h l.ldl.a m.ldl.b s.ldl.c xl.hdl.a l.hdl.b m.hdl.c s.hdl.d
DF$A
以新顺序排列,但具有与以前相同的按字母顺序排列的级别(例如,级别 1 对应于 l.hdl.b,因为这是 [=21 的第一个元素=] 按字母顺序)。看起来像这样:[1] xxl.vldl.a l.vldl.c m.vldl.d s.vldl.f x.vldl.b xs.vldl.h l.ldl.a m.ldl.b s.ldl.c xl.hdl.a l.hdl.b m.hdl.c [13] s.hdl.d Levels: l.hdl.b l.ldl.a l.vldl.c m.hdl.c m.ldl.b m.vldl.d s.hdl.d s.ldl.c s.vldl.f xl.hdl.a xs.vldl.h x.vldl.b xxl.vldl.a
DF$A
新顺序,新等级。看起来像这样:[1] xxl.vldl.a l.vldl.c m.vldl.d s.vldl.f x.vldl.b xs.vldl.h l.ldl.a m.ldl.b s.ldl.c xl.hdl.a l.hdl.b m.hdl.c [13] s.hdl.d Levels: xxl.vldl.a l.vldl.c m.vldl.d s.vldl.f x.vldl.b xs.vldl.h l.ldl.a m.ldl.b s.ldl.c xl.hdl.a l.hdl.b m.hdl.c s.hdl.d
您可能还想为 DF$A 中实际实现的因素设置更多可能的水平,例如如果您稍后要添加更多数据。如果是这样,那么您的输出将如下所示,这三个部分的所有可能顺序都包含在内:
[1] l.ldl.a m.ldl.b s.ldl.c x.vldl.b l.vldl.c m.vldl.d s.vldl.f xs.vldl.h xxl.vldl.a xl.hdl.a l.hdl.b m.hdl.c [13] s.hdl.d 168 Levels: xxl.vldl.a xxl.vldl.b xxl.vldl.c xxl.vldl.d xxl.vldl.f xxl.vldl.h xl.vldl.a xl.vldl.b xl.vldl.c xl.vldl.d xl.vldl.f ... xs.hdl.h
如果其中一个是您想要的,那么这里有一种方法可以完成这些事情:
DF = data.frame(A=factor(c(
'l.ldl.a',
'm.ldl.b',
's.ldl.c',
'x.vldl.b',
'l.vldl.c',
'm.vldl.d',
's.vldl.f',
'xs.vldl.h',
'xxl.vldl.a',
'xl.hdl.a',
'l.hdl.b',
'm.hdl.c',
's.hdl.d')))
first.ordering = c('xxl', 'xl', 'l', 'm', 's', 'x', 'xs')
middle.ordering = c('vldl', 'idl', 'ldl', 'hdl')
last.ordering = c('a', 'b', 'c', 'd', 'f', 'h')
# make a big cartesion product of the orderings,
# making sure that the top-priority orderings are mentioned *last*
# in expand.gird
complete.ordering = with(
expand.grid(last.ordering, first.ordering, middle.ordering),
paste(Var2, Var3, Var1, sep='.'))
new.levels = complete.ordering[complete.ordering %in% DF$A]
A.with.new.levels.but.same.order = factor(DF$A, levels=new.levels)
A.with.new.order.but.same.levels = DF$A[order(as.numeric(A.with.new.levels.but.same.order))]
A.with.new.order.and.levels = factor(A.with.new.order.but.same.levels, levels=new.levels)
A.with.same.order.and.more.levels = factor(DF$A, levels=complete.ordering)
此外,如果您的原始数据框有更多列,例如它看起来像这样:
A another.column
1 l.ldl.a 1
2 m.ldl.b 2
3 s.ldl.c 3
4 x.vldl.b 4
5 l.vldl.c 5
6 m.vldl.d 6
7 s.vldl.f 7
8 xs.vldl.h 8
9 xxl.vldl.a 9
10 xl.hdl.a 10
11 l.hdl.b 11
12 m.hdl.c 12
13 s.hdl.d 13
并且您想将所有行的顺序重新排列在一起,保留每行元素之间的关联,那么您可以执行以下操作:
A.with.new.levels.but.same.order = factor(DF$A, levels=new.levels)
DF.with.new.order = DF[order(as.numeric(A.with.new.levels.but.same.order)),]
这将为您提供以下数据框:
A another.column
9 xxl.vldl.a 9
5 l.vldl.c 5
6 m.vldl.d 6
7 s.vldl.f 7
4 x.vldl.b 4
8 xs.vldl.h 8
1 l.ldl.a 1
2 m.ldl.b 2
3 s.ldl.c 3
10 xl.hdl.a 10
11 l.hdl.b 11
12 m.hdl.c 12
13 s.hdl.d 13
我想建议 tidyr
和 dplyr
作为替代方案。
DF %>%
separate("A", c("first", "middle", "last"), sep="[.]") %>%
arrange(middle, first) %>%
unite(A, c(first, middle,last), sep=".") %>%
mutate(A=as.factor(A))
首先我们把这三个部分分开,排列它们,然后合二为一。最后,我们按照新顺序重做关卡。
这给
A
1 l.hdl.b
2 m.hdl.c
3 s.hdl.d
4 xl.hdl.a
5 l.ldl.a
6 m.ldl.b
7 s.ldl.c
8 l.vldl.c
9 m.vldl.d
10 s.vldl.f
11 x.vldl.b
12 xs.vldl.h
13 xxl.vldl.a
比 levels
答案稍长,但可能更具可读性。