Inverting table - google-sheets

This is the table I have:
A B
1 Title1 | Title
2
3 0 | # of teachers
4
5 11 | # of students
6
7 Not active | Active?
8
9
10
11 Title2 | Title
12
13 3 | # of teachers
14
15 5 | # of students
16
17 Not active | Active?
18
19
20
21 Title3 | Title
22
23 10 | # of teachers
24
25 22 | # of students
26
27 Not active | Active?
I'd like to "invert" it in another sheet to have Title, # of teachers, # of students and Active? as headers and then the values under the right column (each entry in a separate row).
I was trying to use MATCH without much luck..
This retrieves just the first Title (every time):
=index(SheetWithTable!$A:$A,match("Title",SheetWithTable!$B:$B,0))

Please copy your sheet and in that copy select B1:B7, Copy, Paste special into D1 with Paste transpose. In D3, copied across to J3 and down to suit:
=index($A1:$A11,match(D$1,$B1:$B11,0))
Select all, Copy, Paste special, Paste values only. Filter Column B to deselect # of teachers only and delete all rows but Row 1. Clear filter. Delete Columns I, G, E, C, B, A.

Try the following formula in cell D1:
={{B1,B3,B5,B7};{filter(A:A,B:B=B1),filter(A:A,B:B=B3),filter(A:A,B:B=B5),filter(A:A,B:B=B7)}}
Or you can try:
={{"Title","# of teachers","# of students","Active?"};{filter(A:A,B:B="Title"),filter(A:A,B:B="# of teachers"),filter(A:A,B:B="# of students"),filter(A:A,B:B="Active?")}}
Have a look at the following screenshot:

If you have the 3 titles in a table, you can rotate it:
rotateArray = function(array) {
var newArray = [];
for (var i = 0; i < array[0].length; i++) {
newArray[i] = [];
for (var j = 0; j < array.length; j++) {
newArray[i].push(array[j][i]);
}
}
return newArray;
};
http://dtab.io/sheets/560b8efd6faeb39d2a70ad1e

Related

How to return a count of fields with a given value in a record?

I have a database table with the following fields :
---------------------
FIELDS : | H1 | H2 | H3 | H4
---------------------
VALUES : | A | B | A | C
---------------------
For a given record (row), I would like to count the number of fields with a value of A. In the above, for example, there are two fields with a value of A, so the expected result would be : 2
How can I achieve this?
I am trying to answer the question from a database point of view.
You have a table with one or more rows and every row has in the four columns either an 'A' or something else. For a given row (or for many rows) you want to get the number of columns that have an 'A' in it.
As one commenter pointed out you can't sum letters but you can check whether or not a value is the one you are looking for and then count this occurence as a 1 or 0. Finally sum those values and return the sum.
SELECT (CASE H1 WHEN 'A' THEN 1 ELSE 0 END) +
(CASE H2 WHEN 'A' THEN 1 ELSE 0 END) +
(CASE H3 WHEN 'A' THEN 1 ELSE 0 END) +
(CASE H4 WHEN 'A' THEN 1 ELSE 0 END) AS number_of_a
FROM name_of_your_table;
For your example row this will return:
NUMBER_OF_A
===========
2
If you have more than one row you'll get the number of As for every row.
I test this it work Thanx for help.
SELECT count(H1) + count(H2) + count(H3) + count(H4) + count(H5) +
count(H6) + count(H7) + count(H8) as TOT
from Table T
where T.H1 = 'A' or T.H2 = 'A' or T.H3 = 'A' or T.H4 = 'A'
or T.H5 = 'A' or T.H6 = 'A' or T.H7 = 'A' or T.H8 = 'A'
group by T.ID
order by 1 DESC
Other solution ...

How to automatically format data to create a treemap in Google Sheets?

I want to create a treemap from dynamic data in google spreadsheets. So far, I succeeded to have a table in a format that Excel can use, but I don't know how to transform this table in a table that Google sheet can use to create this treemap
Excel can use this data. Not Google sheet.
My data looks like this:
Categories Item Value
__________ ______ _____
category_1 item_1 5
category_1 item_2 20
category_1 item_3 1
category_2 item_4 0
category_2 item_5 5
category_2 item_6 18
category_3 item_7 16
category_4 item_8 7
category_4 item_9 16
I would like to find a way to transform this data into something like the table below, which is usable by Google sheet.
Item Parent Value
__________ __________ _____
Categories 88
category_1 Categories 26
item_1 category_1 5
item_2 category_1 20
item_3 category_1 1
category_2 Categories 23
item_4 category_2 0
item_5 category_2 5
item_6 category_2 18
category_3 Categories 16
item_7 category_3 16
category_4 Categories 23
item_8 category_4 7
item_9 category_4 16
I did not find a way to do that yet and was wondering if anyone had faced the same problem.
Probably you can use this simple script function as an example:
function makeTree() {
var srcRange = SpreadsheetApp.getActiveSheet().getRange('A2:C10'),
tree = {'.Categories': 0}, key;
// Fill tree object with source data
srcRange.getValues().forEach(function(rowValues) {
// Add row value to the root
tree['.Categories'] += rowValues[2];
// Add it to "Category" level
key = 'Categories.' + rowValues[0];
if (tree[key] == undefined) {
tree[key] = rowValues[2];
} else {
tree[key] += rowValues[2];
}
// Add it to "Item" level too
key = rowValues[0] + '.' + rowValues[1];
if (tree[key] == undefined) {
tree[key] = rowValues[2];
} else {
tree[key] += rowValues[2];
}
});
// Format tree rows for output
var values = [];
for (key in tree) {
var subKeys = key.split('.');
values.push([subKeys[1], subKeys[0], tree[key]]);
}
// Fill target data rows
var targetRange = srcRange.offset(0, 4, values.length);
targetRange.setValues(values);
}
Here we collect all data in a single JS object, using composite string keys with a dot delimiter. Ready object is converted to the 2D-array before a target range filling. As a result we have both ranges on the same sheet:

Google Spreadsheet, operations with above row cell in same column with arrayformula

I have arrayformula in the first row of a column so my values and calculations can start in Row 2 and for all the column length.
I have this situation:
https://docs.google.com/spreadsheets/d/11oDra7Vja4-5C0Uix7JTgLLSMG3gPj-6fkajXlWqqQk/edit?usp=sharing
I need a simply arithmetic operation:
Subtract above value of the same column for every row.
I'm using:
=arrayformula(IF(row(A:A)=1; "What I have now"; IF(ISBLANK(A:A); ""; A1:A-A2:A)))
but as you see is wrong.
How to do that?
UPDATED QUESTION:
And then in the second sheet I need a SUM operation with some blank cells in column:
How to do that?
https://docs.google.com/spreadsheets/d/11oDra7Vja4-5C0Uix7JTgLLSMG3gPj-6fkajXlWqqQk/edit#gid=931743679
If you want to have the array formula ion the header this is a bit weird as you need to allow the formula to technically access row 0, we can do this by constructing ranges.
=ArrayFormula(IF(
--(ROW(A1:A) > 2) + -ISBLANK(A1:A) = 1;
{0; A1:A} - {0; A2:A; 0};
""))
--(ROW(A1:A) > 2) + -ISBLANK(A1:A) = 1 Checks if the row is populated and not one of the first two rows in a way that works nicely with array formulas
{0; A1:A} - {0; A2:A; 0} does the following:
0 Data 156 123 110 95 42
- - - - - - -
0 156 123 110 95 42 0
= = = = = = =
0 33 13 15 53 42 42
N N Y Y Y Y N <- Is shown
^ ^ ^
| | Because Row is blank
| |
Because row not > 2, thus it is never evalauated even though the second would cause an error
I think this is quite tricky. The problem is that in an array formula the number of cells in each array must match - you can't mix an array starting in row 1 with an array starting in row 2 if they go all the way to the bottom of the spreadsheet.
Here is one way of getting the result you want
=arrayformula({"What I need";"";offset($A$1,1,0,count(A:A)-1)-offset($A$1,2,0,count(A:A)-1)})
You will need to change the ; and , for your locale.
I have built up an array using the {} notation to define the elements. In my locale a ; means go to the next row, so I have defined the first two cells directly as strings. After that I've chosen to use Offset to get the range A2:A5 (1 row down from A1, 0 rows across and 4 cells high) and subtract the range A3:A6 (2 rows down from A1, 0 rows across and 4 cells high) it so that gives me the other 4 cells.
B1 "What I need"
B2 ""
B3 A3-A2=33
B4 A4-A3=13
B5 A5-A4=15
B6 A6-A5=53
but will need an IF statement adding if there are any blank cells between the numbers.
In the particular case of your updated question where there are fewer numbers in column D than column C, the formula would be
=arrayformula({"Special Case";"";offset($D$1,1,0,count(D:D))+offset($C$1,2,0,count(D:D))})
But in the general case of there being blank cells anywhere, you would have to test everything
=arrayformula({"General Case";"";if(offset($D$1,1,0,rows(C:C)-2)="","",if(offset($C$1,2,0,Rows(C:C)-2)="","",offset($D$1,1,0,rows(C:C)-2)+offset($C$1,2,0,Rows(C:C)-2)))})

Remove rows that are near duplicate of previous row in Deedle dataframe

I have a Deedle Data frame that looks like this.
val it : Frame<int,string> =
Date size1 size2
13 -> 2013-12-12T00:00:00.103336Z 133 35
14 -> 2013-12-12T00:00:00.105184Z 83 35
15 -> 2013-12-12T00:00:00.107205Z 83 35
16 -> 2013-12-12T00:00:00.109566Z 83 34
17 -> 2013-12-12T00:00:00.115260Z 83 34
18 -> 2013-12-12T00:00:00.133546Z 83 34
20 -> 2013-12-12T00:00:00.138204Z 82 34
22 -> 2013-12-12T00:00:00.140125Z 81 34
I would like to remove rows that have the same values for both size1 and size2 as the previous row. In pseudo code...
if row?size1 = prevRow?size1 && row?size2 = prevRow?size2 then dropRow
So in the example above I would end up with:
val it : Frame<int,string> =
Date size1 size2
13 -> 2013-12-12T00:00:00.103336Z 133 35
14 -> 2013-12-12T00:00:00.105184Z 83 35
16 -> 2013-12-12T00:00:00.109566Z 83 34
20 -> 2013-12-12T00:00:00.138204Z 82 34
22 -> 2013-12-12T00:00:00.140125Z 81 34
I believe I want to use
Frame.filterRowValues(row - > )
But I don't see how to compare one row against the previous row. Is there a simple way to do this? Perhaps I need to shift and join?
This can be done using a number of ways and I'm not quite sure which is the best one:
Use shift and join (as you say) would certainly work - you'd need to rename the columns in one of the frames so that you can join them, but it sounds like quite a good solution to me
You can use frame.Rows |> Series.pairwise to get tuples containing the current and the previous row, then use Series.filter and Series.map (to select the second row from the tuple) and re-construct frame using Frame.ofRows. The only issue is that you'll always lost the first row this way (and you'll have to add it back).
You can use Frame.filter and find the previous row. The recent release supports Lookup.Smaller which lets you do that easily.
The code for the third option looks like this (note that the frame rows need to be ordered frame.Rows.IsOrdered = true) for this to work:
frame |> Frame.filterRows (fun k row ->
let prev = frame.Rows |> Series.tryLookup k Lookup.Smaller // New in v1.0
match prev with
| Some prev -> prev?Something <> row?Something
| _ -> true (* always return true for the first row *) )

Problem with DISTINCT and Linq2SQL

I have a table like this:
idinterpretation | iddictionary | idword | meaning
1 1 1115 hello
2 1 1115 hi
3 1 1115 hi, bro
5 1 1118 good bye
6 1 1118 bye-bye
7 2 1119 yes
8 2 1119 yeah
9 2 1119 all rigth
And i try to get distinct rows (DISTINCT idword). So, at first i tried:
return dc.interpretations.Where(i => i.iddictionary == iddict).
ToList<interpretation>().Distinct(new WordsInDictionaryDistinct()).
OrderBy(w => w.word.word1).Skip(iSkip).Take(iTake);
But i have about 300.000 rows in my table and it is wrong solution.
Then, i tried:
IEnumerable<interpretation> res = (from interp in dc.interpretations
group interp by interp.idword into groupedres
select new interpretation
{
idword = groupedres.Key,
idinterpretation = groupedres.SingleOrDefault(i => i.idword == groupedres.Key).idinterpretation,
interpretation1 = groupedres.SingleOrDefault(i => i.idword == groupedres.Key).interpretation1,
iddictionary = groupedres.SingleOrDefault(i => i.idword == groupedres.Key).iddictionary
}).Skip(iSkip).Take(iTake);
and i took error: #foreach (interpretation interp in ViewBag.Interps) System.NotSupportedException: Explicit construction of entity type 'vslovare.Models.interpretation' in query is not allowed.
Is it really a way to take distinct rows and to have in finish rows like this:
idinterpretation | iddictionary | idword | meaning
1 1 1115 hello
5 1 1118 good bye
7 2 1119 yes
?
dictionaries:
dictionary table
iddictionary | dictionary_name
words:
word table
idword | word_name
interpretations:
interpretation table
idinterpretation | iddictionary | idword | meaning
I think your second attempt is almost there - you probably need to use a GroupBy clause to get this working within SQL.
Something like:
var query = from row in dc.interpretations
where row.iddictionary == iddict
group row by idword into grouped
select grouped.FirstOrDefault();
return query.OrderBy(w => w.word.word1).Skip(iSkip).Take(iTake);
On why your query is taking too long - in general, if your query is slow it will be because the data you are searching and returning is really large - or because it is poorly indexed at the database level. To help find out, it is analysing or profiling your query - see this article on MSDN http://msdn.microsoft.com/en-us/magazine/cc163749.aspx

Resources