我有一个数据框,其中包含许多公司信息,并用id变量分隔。我想对变量之一进行排序,并为每个id重复它。让我们以这个例子为例,
df <- structure(list(id = c(110, 110, 110, 90, 90, 90, 90, 252, 252
), var1 = c(26, 21, 54, 10, 18, 9, 16, 54, 39), var2 = c(234,
12, 43, 32, 21, 19, 16, 34, 44)), .Names = c("id", "var1", "var2"
), row.names = c(NA, -9L), class = "data.frame")
看起来像这样
df
id var1 var2
1 110 26 234
2 110 21 12
3 110 54 43
4 90 10 32
5 90 18 21
6 90 9 19
7 90 16 16
8 252 54 34
9 252 39 44
现在,我想通过向量var1
根据id
对数据帧进行排序。我能想到的最简单的解决方案是使用apply
函数,
> apply(df, 2, sort)
id var1 var2
[1,] 90 9 12
[2,] 90 10 16
[3,] 90 16 19
[4,] 90 18 21
[5,] 110 21 32
[6,] 110 26 34
[7,] 110 39 43
[8,] 252 54 44
[9,] 252 54 234
但是,这不是我想要的输出。正确的输出应为
id var1 var2
1 110 21 12
2 110 26 234
3 110 54 43
4 90 9 19
5 90 10 32
6 90 16 16
7 90 18 21
8 252 39 44
9 252 54 34
按id
分组并按var1
列进行排序,并且保持原始的id
列顺序。
有人知道如何排序吗?
答案 0 :(得分:6)
另一个使用order
和match
的基本R选项
df[with(df, order(match(id, unique(id)), var1, var2)), ]
# id var1 var2
#2 110 21 12
#1 110 26 234
#3 110 54 43
#6 90 9 19
#4 90 10 32
#7 90 16 16
#5 90 18 21
#9 252 39 44
#8 252 54 34
答案 1 :(得分:6)
注意。如Moody_Mudskipper所述,无需使用tidyverse
,也可以使用基础R
轻松完成:
df[order(ordered(df$id, unique(df$id)), df$var1), ]
没有任何tidyverse
变量的单线temp
解决方案:
library(tidyverse)
df %>% arrange(ordered(id, unique(id)), var1)
# id var1 var2
# 1 110 26 234
# 2 110 21 12
# 3 110 54 43
# 4 90 10 32
# 5 90 18 21
# 6 90 9 19
# 7 90 16 16
# 8 252 54 34
# 9 252 39 44
说明apply(df, 2, sort)
不起作用的原因
您试图做的是对每一列进行独立排序。 apply
在指定的维度上运行(在这种情况下,2
与列相对应)并应用函数(在这种情况下,sort
)。
apply
试图进一步简化结果,在这种情况下,简化为矩阵。因此,您将获得一个矩阵(不是一个data.frame
),其中每个列均独立排序。例如,来自apply
调用的这一行:
# [1,] 90 9 12
甚至在原始data.frame
中也不存在。
答案 2 :(得分:3)
我们可以将id
转换为因数,以便在保留原始顺序的同时进行拆分。然后,我们可以遍历列表和顺序,然后再次rbind
,即
df$id <- factor(df$id, levels = unique(df$id))
do.call(rbind, lapply(split(df, df$id), function(i)i[order(i$var1),]))
# id var1 var2
#110.2 110 21 12
#110.1 110 26 234
#110.3 110 54 43
#90.6 90 9 19
#90.4 90 10 32
#90.7 90 16 16
#90.5 90 18 21
#252.9 252 39 44
#252.8 252 54 34
注意:您可以通过rownames(new_df) <- NULL
答案 3 :(得分:3)
在基础 public static void listItems() throws Exception {
ItemView view = new ItemView(100);
FolderView view1 = new FolderView(100);
Folder folder = Folder.bind(service, WellKnownFolderName.MsgFolderRoot);
SearchFilter filterFolder = new SearchFilter.IsEqualTo(FolderSchema.DisplayName,"Posteingang");
FindItemsResults<Item> findInbox = service.findItems(new FolderId(uniqueId),view);
FindFoldersResults findFolderResults = folder.findFolders(filterFolder, view1);
service.loadPropertiesForFolder(folder, PropertySet.FirstClassProperties);
service.loadPropertiesForItems(findInbox, PropertySet.FirstClassProperties);
for (Folder f : findFolderResults.getFolders()) {
System.out.println("Displayname=====" + f.getDisplayName());
for (Item item : findInbox.getItems()) {
System.out.println("sub==========" + item.getSubject());
System.out.println(item.getClass());
counter++;
}
}
System.out.println(counter);
}
中,我们可以使用R
:
split<-
或@Markus建议:
split(df,df$id) <- lapply(split(df,df$id), function(x) x[order(x$var1),] )
在两种情况下的输出:
split(df, df$id) <- by(df, df$id, function(x) x[order(x$var1),])
答案 4 :(得分:2)
通过下面的tidyverse
管道,将复制问题的输出。
library(tidyverse)
df %>%
mutate(tmp = cumsum(c(0, diff(id) != 0))) %>%
group_by(id) %>%
arrange(tmp, var1) %>%
select(-tmp)
## A tibble: 9 x 3
## Groups: id [3]
# id var1 var2
# <dbl> <dbl> <dbl>
#1 110 21 12
#2 110 26 234
#3 110 54 43
#4 90 9 19
#5 90 10 32
#6 90 16 16
#7 90 18 21
#8 252 39 44
#9 252 54 34