I am trying to get the most consecutive wins for a team. Firstly I have specified the win and lost results for every team but I have no idea how to get the most consecutive wins for the team
MATCH (a:TeamFootbal )-[r]->(m:Games)<-[r2]-(op:TeamFootbal)
with a.name as teamnames,
case when r.scores > r2.scores then 1 else 0 end as result
return teamnames, result
order by teamnames
The output will be like this
Team Name Result
A 1
A 1
A 1
A 0
A 1
B 1
B 1
B 1
B 1
B 0
C 1
C 0
C 1
C 1
C 0
D 0
D 1
D 0
D 0
D 1
E 1
E 1
E 1
E 1
E 0
I want to get
B 4
E 4
without using the apoc procedure
I adapted my answer to a similar question:
MATCH (a:TeamFootbal)-[r]->(m:Games)<-[r2]-(op:TeamFootbal)
WITH
a.name AS teamname,
CASE WHEN r.scores > r2.scores THEN 1 ELSE 0 END AS result
ORDER BY m.date ASC // (*)
WITH teamname AS s, collect([teamname, result]) AS p
WITH s, reduce(acc = [], i IN range(0, size(p) - 1) |
CASE p[i] = p[i-1]
WHEN true THEN [j IN range(0, size(acc) - 1) |
CASE j = size(acc) - 1
WHEN true THEN acc[j] + [p[i]]
ELSE acc[j]
END
]
ELSE acc + [[p[i]]]
END
) AS streaks
UNWIND streaks AS streak
WITH s, streak
WHERE streak[0] <> 0
RETURN s, max(size(streak)) AS consecutivePasses
Note that ordering should be inserted at (*)
Here is a little trick to search the max number of following 1 in a list :
WITH [1,0,0,1,1,1,0,1,1,1,1] AS results
RETURN
reduce(
// current value, highest value so far
x=[0,0],
i IN results |
CASE
WHEN i=0 THEN [0 , x[1]]
WHEN (x[0]+i) > x[1] THEN [x[0] +1 , x[0]+1]
ELSE [x[0] +1 , x[1]]
END
)
Related
I have a given matrix H and I would like to unfold (expand) it to find a matrix B by following the method below :
Let H be a matrix of dimension m × n. Let x = gcd (m,n)
The matrix H is cut in two parts.
The cutting pattern being such that :
The "diagonal cut" is made by alternately moving c = n/x units to the right (we move c units to the right several times).
We alternately move c-b = m/x units down (i.e. b = (n-m)/x) (we move b units down several times).
After applying this "diagonal cut" of the matrix, we copy and paste the two parts repeatedly to obtain the matrix B.
Exemple : Let the matrix H of dimension m × n = 5 × 10 defined by :
1 0 1 1 1 0 1 1 0 0
0 1 1 0 0 1 1 0 1 1
1 1 0 1 1 1 0 1 0 0
0 1 1 0 1 0 1 0 1 1
1 0 0 1 0 1 0 1 1 1
Let's calculate x = gcd (m,n) = gcd (5,10) = 5,
Alternatively move to the right : c = n/x = 10/5 = 2,
Alternatively move down : b = (n-m)/x = (10-5)/5 = 1.
Diagonal cutting diagram : The matrix H is cut in two parts.
The cutting pattern is such that :
We move c = 2 units to the right several times c = 2 units to the right,
We repeatedly move c - b = 1 unit downwards.
We get :
After applying this "diagonal cut" of the matrix, we copy and paste the two parts repeatedly to obtain the matrix :
Remark : In the matrices X, X1 and X2 the dashes are zeros.
The resulting matrix B is (L is factor) :
Any suggestions?
This can be done by creating a logical mask with the cutting pattern, and then element-wise multiplying the input by the mask and by its negation. Repeating by L can be done with blkdiag.
H = [1 0 1 1 1 0 1 1 0 0
0 1 1 0 0 1 1 0 1 1
1 1 0 1 1 1 0 1 0 0
0 1 1 0 1 0 1 0 1 1
1 0 0 1 0 1 0 1 1 1];
L = 2;
[m, n] = size(H);
x = gcd(m, n);
c = n / x;
b = (n-m)/x;
mask = repelem(tril(true(m/b)), b, c);
A = [H.*mask; H.*~mask];
A = repmat({A}, L, 1);
B = blkdiag(A{:});
I have a 1 by 1000 (1 row by 1000 columns) matrix that contain only 0 and 1 as their elements. How can I find how many times 1 is repeated 3 times consecutively.
If there are more than 3 ones then it is necessary to reset the counting. So 4 would be 3+1 and it counts as only one instance of 3 consecutive 1s but 6 would be 3+3 so it counts as two instances of having 3 consecutive 1s.
This approach finds the differences between when A goes from 0 to 1 (rising edge) and from 1 to 0 (falling edge). This gives the lengths of consecutive 1s in each block. Then divide these numbers by 3 and round down to get the number of runs of 3.
Padding A with a 0 at the start and end just ensures we have a rising edge at the start if A starts with a 1, and we have a falling edge at the end if A ends with a 1.
A = round(rand(1,1000));
% padding with a 0 at the start and end will make this simpler
B = [0,A,0];
rising_edges = ~B(1:end-1) & B(2:end);
falling_edges = B(1:end-1) & ~B(2:end);
lengths_of_ones = find(falling_edges) - find(rising_edges);
N = sum(floor(lengths_of_ones / 3));
Or in a much less readable 2 lines:
A = round(rand(1,1000));
B = [0,A,0];
N = sum(floor((find(B(1:end-1) & ~B(2:end)) - find(~B(1:end-1) & B(2:end))) / 3));
You can define your custom functions like below
v = randi([0,1],1,1000);
% get runs in cell array
function C = runs(v)
C{1} = v(1);
for k = 2:length(v)
if v(k) == C{end}(end)
C{end} = [C{end},v(k)];
else
C{end+1} = v(k);
end
end
end
% count times of 3 consecutive 1s
function y = count(x)
if all(x)
y = floor(length(x)/3);
else
y = 0;
end
end
sum(cellfun(#count,runs(v)))
Here is another vectorized way:
% input
n = 3;
a = [1 1 1 1 0 0 1 1 1 0 0 0 1 1 1 1 1 0 1 1 1 1 1 1 1]
% x x x x x = 5
% output
a0 = [a 0];
b = cumsum( a0 ) % cumsum
c = diff( [0 b( ~( diff(a0) + 1 ) ) ] ) % number of ones within group
countsOf3 = sum( floor( c/n ) ) % groups of 3
You like it messy? Here is a one-liner:
countsOf3 = sum(floor(diff([0 getfield(cumsum([a 0]),{~(diff([a 0])+1)})])/n))
How to sum only consecutive duplicate numbers in order to find a unique value? for example, I have a vector
A = [0 0 0 0 1 0 0 0 1 0 1 1 0 0 1 0 1]
then when summing only consecutive duplicate numbers, I will have
B = [0 1 0 1 0 2 0 1 0 1]
finally the number of unique values different from 0 and 1 :
sum(B>1)
I know one way to solve the problem:
sum(diff(find(A==1))==1)
but it seems it is not a good method.
An alternative solution:
A = [0 0 0 0 1 0 0 0 1 0 1 1 0 0 1 0 1]
%// get Islands
a = cumsum(~A)
b = a(logical(A))
%// count occurences
c = histc(b,unique(b))
%// count number of occurences > 1
d = sum(c > 1)
%// or sum of occurences > 1
e = sum(c(c > 1))
c =
1 1 2 1 1
d =
1
e =
2
This will give you the total number of repeated values in the array including "0" values.
sum(A(1:end-1)-A(2:end)==0)
ans =
7
If you are interested only in the repeated "1" values, you can change it to
sum(A(1:end-1)+A(2:end)==2)
ans =
1
Note that this is the count of duplicates if you have [1 1 1] you'll get 2 not 1.
I have a dataset with about 20 million rows with the following format:
Userid attributid timeid
1 -1 0
1 -2 0
1 -3 0
1 -4 0
1 -5 0
...
and another index that match the attributeid to one of the four attribute type:
attributeid attributetype
-1 A
-2 B
-3 C
-4 D
-5 B
I would like to batch import the dataset into neo4j by converting it into the following format:
UserID A B C D timeid
1 -1 -2,-5 -3 -4 0
I tried R by order the dataframe using userid and scanning through it. But it was too slow. I was wondering what is the most time efficient way to do that? Or is there any thing I can do to optimize my code? Here is my code:
names(node_attri)[1] = 'UserID'
names(node_attri)[2] = 'AttriID'
names(node_attri)[3] = 'TimeID'
names(attri_type)[1] = 'AttriID'
names(attri_type)[2] = 'AttriType'
#attri_type <- attri_type[order(attri_type),]
#node_attri <- node_attri[order(node_attri),]
N = length(unique(node_attri$TimeID))*length(unique(node_attri$UserID))
new_nodes = data.frame(UserID=rep(NA,N), employer=rep(NA,N), major=rep(NA,N),
places_lived=rep(NA,N), school=rep(NA,N), TimeID=rep(NA,N))
row = 0
start = 1
end = 1
M =nrow(node_attri)
while(start <= M) {
row = row + 1
em = ''
ma = ''
pl = ''
sc = ''
while(node_attri[start,1] == node_attri[end,1]) {
if (attri_type[abs(node_attri[end,2]),2] == 'employer')
em = paste(em, node_attri[end,2], sep=',')
else if (attri_type[abs(node_attri[end,2]),2] == 'major')
ma = paste(ma, node_attri[end,2], sep=',')
else if (attri_type[abs(node_attri[end,2]),2] == 'places_lived')
pl = paste(pl, node_attri[end,2], sep=',')
else if (attri_type[abs(node_attri[end,2]),2] == 'school')
sc = paste(sc, node_attri[end,2], sep=',')
end = end + 1
if (end > M) break
}
new_nodes[row,] = list(UserID=node_attri[start,1], employer=substring(em,2),
major=substring(ma,2), places_lived=substring(pl,2),
school=substring(sc,2), TimeID=node_attri[start,3])
start = end
end = start
}
new_nodes = new_nodes[1:row,]
You need to merge, aggregate and then reshape. Assuming your dataframes are DFand DF2respectively:
x <- merge(DF, DF2)
y <- aggregate(attributeid~., data=x, FUN=function(x)paste(x, collapse=","))
z <- reshape(y, direction="wide", idvar=c("Userid","timeid"), timevar="attributetype")
Result:
> z
Userid timeid attributeid.A attributeid.B attributeid.C attributeid.D
1 1 0 -1 -5,-2 -3 -4
Renaming and rearranging columns is trivial.
Here is a solution using the reshape2 package and match.
library(reshape2)
##Create some sample data
dat1 <- data.frame(Userid=rep(1:4,each=5),attributeid=rep(-1:-5,4),timeid=rep(0:3,each=5))
index <- data.frame(attruibuteid=-1:-5,attributetype=c("A","B","C","D","B"))
##Merge the two using match
dat1$attributetype = index$attributetype[match(dat1$attributeid,index$attruibuteid)]
##Reformat using aggregate and dcast
dat2 <- aggregate(attributeid~attributetype+timeid+Userid,function(x){paste(x,collapse=",")},data=dat1)
dat3 <- dcast(formula=Userid+timeid~attributetype,value.var="attributeid",data=dat2)
> dat3
Userid timeid A B C D
1 1 0 -1 -2,-5 -3 -4
2 2 1 -1 -2,-5 -3 -4
3 3 2 -1 -2,-5 -3 -4
4 4 3 -1 -2,-5 -3 -4
I have a user function that returns a BIT calle dbo.IsPartReady.
I am trying to use the function inside of a trigger as follows:
SET #railReady = dbo.IsPartReady(1,#curPartiId);
SET #frameReady = dbo.IsPartReady(2,#curPartiId);
SET #dryAReady = dbo.IsPartReady(3,#curPartiId);
SET #dryBReady = dbo.IsPartReady(4,#curPartiId);
IF ( (#railReady AND #frameReady ) OR ( #dryAReady AND #dryBReady ) )
I'm getting the following error in the IF statement:
An expression of non-boolean type specified in a context where a condition is expected, near 'AND'.
What am I doing wrong ?
BIT data type in SQL Server is not a boolean it is an integer. You have to compare the value of the variable with something to get a boolean expression. BIT can have the value 0, 1 or NULL.
http://msdn.microsoft.com/en-us/library/ms177603.aspx
declare #B bit = 1
if #B = 1
begin
print 'Yes'
end
Use the following:
IF ((#railReady = 1 AND #frameReady = 1) OR (#dryAReady = 1 AND #dryBReady = 1))
or alternatively,
IF ((#railReady & #frameReady) | (#dryAReady & #dryBReady)) = 1
More information:
To verify this we can use a truth table containing all combinations of four bit values:
WITH B(x) AS (SELECT CAST(0 AS bit) UNION ALL SELECT CAST(1 AS bit))
, AllSixteenCombinations(a,b,c,d) AS
(SELECT * FROM B B1 CROSS JOIN B B2 CROSS JOIN B B3 CROSS JOIN B B4)
SELECT a,b,c,d
, CASE WHEN ((a = 1 AND b = 1) OR (c = 1 AND d = 1)) THEN 'Y' ELSE 'N' END[Logic]
, CASE WHEN ((a & b) | (c & d)) = 1 THEN 'Y' ELSE 'N' END [Bitwise]
FROM AllSixteenCombinations
Output:
a b c d Logic Bitwise
----- ----- ----- ----- ----- -------
0 0 0 0 N N
0 1 0 0 N N
0 0 1 0 N N
0 1 1 0 N N
1 0 0 0 N N
1 1 0 0 Y Y
1 0 1 0 N N
1 1 1 0 Y Y
0 0 0 1 N N
0 1 0 1 N N
0 0 1 1 Y Y
0 1 1 1 Y Y
1 0 0 1 N N
1 1 0 1 Y Y
1 0 1 1 Y Y
1 1 1 1 Y Y
(16 row(s) affected)