我有两列,只想保留非交换行。对于下面的数据,我的输出应该包含一个(1 2)的组合。即,对于我的查询(1 2)与(2 1)相同。有没有一种简单的方法在R中做到这一点。已经尝试过调换。并保留上部的traingular矩阵。但转移数据变得很痛苦。
<div id = "first">0</div>
<div id = "second">0</div>
<button type="button" id="but">
Shift 0,0
</button>
我的最终输出应该是:
A B prob
1 2 0.1
1 3 0.2
1 4 0.3
2 1 0.3
2 3 0.1
2 4 0.4
答案 0 :(得分:7)
我们可以独立sort()
每行,然后使用$a == $b
duplicated()
查找要保留的行:
!
数据强>
df[!duplicated(t(apply(df[1:2],1L,sort))),];
## A B prob
## 1 1 2 0.1
## 2 1 3 0.2
## 3 1 4 0.3
## 5 2 3 0.1
## 6 2 4 0.4
第一步是仅提取两个感兴趣的列:
df <- data.frame(A=c(1L,1L,1L,2L,2L,2L),B=c(2L,3L,4L,1L,3L,4L),prob=c(0.1,0.2,0.3,0.3,0.1,0.4
));
然后我们使用apply()
和df[1:2];
## A B
## 1 1 2
## 2 1 3
## 3 1 4
## 4 2 1
## 5 2 3
## 6 2 4
sort()
正如您所看到的,apply(df[1:2],1L,sort);
## [,1] [,2] [,3] [,4] [,5] [,6]
## [1,] 1 1 1 1 2 2
## [2,] 2 3 4 2 3 4
会在意外转置中返回其结果,因此我们必须使用t()
进行修复,以便为即将到来的apply()
电话做准备:
duplicated()
现在我们可以使用t(apply(df[1:2],1L,sort));
## [,1] [,2]
## [1,] 1 2
## [2,] 1 3
## [3,] 1 4
## [4,] 1 2
## [5,] 2 3
## [6,] 2 4
来获取一个逻辑向量,指示哪些行与前一行重复:
duplicated()
然后我们用一个否定反转逻辑向量,得到那些不重复任何前一行的行:
duplicated(t(apply(df[1:2],1L,sort)));
## [1] FALSE FALSE FALSE TRUE FALSE FALSE
最后,我们可以使用生成的逻辑向量来索引!duplicated(t(apply(df[1:2],1L,sort)));
## [1] TRUE TRUE TRUE FALSE TRUE TRUE
的那些不与之前任何行重复的行:
df
因此,将保留每组排序后重复项的第一次次出现,其余部分将被删除。
来自@RichardScriven的优秀建议;我们可以使用df[!duplicated(t(apply(df[1:2],1L,sort))),];
## A B prob
## 1 1 2 0.1
## 2 1 3 0.2
## 3 1 4 0.3
## 5 2 3 0.1
## 6 2 4 0.4
的{{1}}参数替换t()
调用,这可能会稍快一点:
MARGIN
答案 1 :(得分:3)
我们可以使用data.table
。转换&#39; data.frame&#39;到&#39; data.table&#39; (setDT(df1)
),按pmin(A, B)
和pmax(A,B)
分组,if
行数大于1,我们得到第一行或else
返回行。
library(data.table)
setDT(df1)[, if(.N >1) head(.SD, 1) else .SD ,.(A=pmin(A, B), B= pmax(A, B))]
# A B prob
#1: 1 2 0.1
#2: 1 3 0.2
#3: 1 4 0.3
#4: 2 3 0.1
#5: 2 4 0.4
或者我们可以在duplicated
,pmax
输出上使用pmin
来返回逻辑索引并根据该数据对数据进行子集化。
setDT(df1)[!duplicated(cbind(pmax(A, B), pmin(A, B)))]
# A B prob
#1: 1 2 0.1
#2: 1 3 0.2
#3: 1 4 0.3
#4: 2 3 0.1
#5: 2 4 0.4
答案 2 :(得分:1)
这应该有效:
import java.util.Date;
import java.util.LinkedHashMap;
import java.util.Map;
import java.util.concurrent.TimeUnit;
public class TimeAgo {
public static final Map<String, Long> times = new LinkedHashMap<>();
static {
times.put("year", TimeUnit.DAYS.toMillis(365));
times.put("month", TimeUnit.DAYS.toMillis(30));
times.put("week", TimeUnit.DAYS.toMillis(7));
times.put("day", TimeUnit.DAYS.toMillis(1));
times.put("hour", TimeUnit.HOURS.toMillis(1));
times.put("minute", TimeUnit.MINUTES.toMillis(1));
times.put("second", TimeUnit.SECONDS.toMillis(1));
}
public static String toRelative(long duration, int maxLevel) {
StringBuilder res = new StringBuilder();
int level = 0;
for (Map.Entry<String, Long> time : times.entrySet()){
long timeDelta = duration / time.getValue();
if (timeDelta > 0){
res.append(timeDelta)
.append(" ")
.append(time.getKey())
.append(timeDelta > 1 ? "s" : "")
.append(", ");
duration -= time.getValue() * timeDelta;
level++;
}
if (level == maxLevel){
break;
}
}
if ("".equals(res.toString())) {
return "0 seconds ago";
} else {
res.setLength(res.length() - 2);
res.append(" ago");
return res.toString();
}
}
public static String toRelative(long duration) {
return toRelative(duration, times.size());
}
public static String toRelative(Date start, Date end){
assert start.after(end);
return toRelative(end.getTime() - start.getTime());
}
public static String toRelative(Date start, Date end, int level){
assert start.after(end);
return toRelative(end.getTime() - start.getTime(), level);
}
}
请注意,这将使用模式的第一次出现。
答案 3 :(得分:0)
这是使用基础R的另一个解决方案。想法是在df
的后半部分(使用sapply
)搜索,如果有任何重复。然后我们返回secondHalf
向量。我们会从df
进一步删除这些行。
n <- nrow(df)
secondHalf <- sapply(seq(n/2), function(i) nrow(df[df$A==df[i,2] & df$B==df[i,1],]))
# [1] 1 0 0
toRemove <- ((floor(n/2)+1):n)*secondHalf
df <- df[-toRemove,]
# A B prob
# 1 1 2 0.1
# 2 1 3 0.2
# 3 1 4 0.3
# 5 2 3 0.1
# 6 2 4 0.4