writer string and formula till the data available for particular range - python-2.7

I have data in excel and wanted to write a string with a sum for each group of the table.
So I wanted to loop through in a range and write a string "Subtotal" on the first column and apply formula '=sum{}:{}' from start row to before I'm writing a formula.
I know the start and end range.
How can I achieve that by using a loop where the first blank found write string and formula.
input:
See below code I'm trying but it does not work.
row_start = number_rows_placement + number_rows_adsize + 20
row_end = number_rows_placement + number_rows_adsize + number_rows_daily + unqiue_final_day_wise * 5 + 15
for i in range ( row_start , row_end ):
if i == " ":
worksheet.write(i,1,"Subtotal", format)
i += 5
worksheet.write_formula(i,2,'=sum(:)', format)
but it doesn't seem to be working. I don't know where I'm wrong. also while trying to get sum range would vary after each header to before the formula marked.
OutPut:

The formula isn't valid in Excel. It should be =SUM(), uppercase.
Also, you can generate the range for the formula with something like this:
from xlsxwriter.utility import xl_range
row_start = 60
row_end = 64
col = 1
cell_range = xl_range(row_start, col, row_end, col) # B61:B65
See the XlsxWriter Cell Utility Functions.

Related

convert 12 7-12 to superscript 12⁷⁻¹/² is there a way to reduce length of / and the 12 7-1/2 is in one cell. I converted it manually with code below

function to convert to superscript
def get_super(x):
normal = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+-=()"
super_s = "ᴬᴮᶜᴰᴱᶠᴳᴴᴵᴶᴷᴸᴹᴺᴼᴾQᴿˢᵀᵁⱽᵂˣʸᶻᵃᵇᶜᵈᵉᶠᵍʰᶦʲᵏˡᵐⁿᵒᵖ۹ʳˢᵗᵘᵛʷˣʸᶻ⁰¹²³⁴⁵⁶⁷⁸⁹⁺⁻⁼⁽⁾"
res = x.maketrans(''.join(normal), ''.join(super_s))
return x.translate(res)
display superscipt
print('12' + get_super('7-1/2')) # result 12⁷⁻¹/² the 12 added manually need to automate. have 12000 rows and 5 columns. will the elongated / affect calculations?

Regular expression in Matlab to leave only specified items of an array

I have a list of channels:
channels = {'1LT1', '1LT2', '1LT3', '1LT4', '1LT5', '2LA1', '2LA2', '2LA3', '3LH1', '3LH5', '4LT1', '4LT2', '4LT3', '5LH1', '5LH2', '4LT10'}
I need to write an alogrithm to leave only distal channels. It means for each type of channel ('1LT', '2LA', '3LH', '4LT' and etc.) I need only channel with the highest last number. The best way is to return indexes of these channels. For example, for abovementioned list the results should be:
[5, 8, 10, 15, 16]
I think I can do it with regexp by splitting like that:
row_i = 1;
for ch_i=[1:length(channels)]
try
[n(row_i,:), ch_type(row_i,:)] = strsplit(channels{ch_i},'\d+[A-Z]', 'DelimiterType','RegularExpression');
row_i = row_i + 1;
catch
continue
end
end
But then I am really stuck. Can somebody give me some tips to create good algorithm?
I am thankful for any idea!
You can use regexp to break each string into a channel and number, create numeric labels for the channels using findgroups, convert the number string into an actual number with str2double, then splitapply to find the max for each group. Here's the code, although I can't test it right now so it may need some tweaks:
tokens = regexp(channels, '(\d+[A-Z]+)(\d+)', 'tokens');
tokens = vertcat(tokens{:});
[grps, channelID] = findgroups(tokens(:, 1));
nums = str2double(tokens(:, 2));
channelMax = splitapply(#max, nums, grps);
Using the channelID and channelMax values, you can then reconstruct the distal channel names and find their indices in the channel list using sprintf, strsplit, and ismember:
distal = strsplit(sprintf('%s%d\n', channelID, channelMax));
index = find(ismember(channels, distal));

How to generate item variables from total score variable

I want to simulate the item score from total score.
For example, I have generated the total score, which has scores between 5 and 25. I would like to distribute this total score to five items with each having a 5-Likert score.
Then I used a while loop to check the condition in Stata 15. The code takes took too long to finish looping and I do not know whether I have made a mistake.
Perhaps someone would like to suggest another way to simulate the item score from the total score?
My code:
set obs 200
generate id=_n
generate u_i= rnormal(0, 0.5)
generate gr = runiform()>0.5
generate sex = runiform()>0.4
generate age = round(rnormal(65, 10))
expand 5
bysort id: generate time=_n
generate e_ij = rnormal(0, 1.0)
generate run=_n
*Generate Sum score 5-25
generate y = 3.0 + 2.0*gr + 0.2*age -1.2*sex + 0.5*time + u_i + e_ij
summarize y
replace y = round(y)
*Generate each item
forvalues k = 1(1)5 {
generate item`k' = runiform(1, 5)
replace item`k' = round(item`k')
}
egen sum_item=rowtotal(item1 item2 item3 item4 item5)
generate diff = y - sum_item
*Looping check if y=sum_item
forvalues a = 1(1)`=_N' {
quietly gsort -diff
while sum_item!=y[`a'] {
replace sum_item=. if sum_item!=y[_n]
forvalues k = 1(1)5 {
replace item`k' =. if sum_item==.
replace item`k' = runiform(1, 5) if item`k'==.
replace item`k' = round(item`k')
}
replace sum_item= item1 + item2+item3+item4+item5 if sum_item==.
replace diff = y - sum_item
if (sum_item==y[`a']) continue, break
}
}
The expected data that I would like to have:
As you can see, after running the loop I will always get 2-4 cases that the program keep running by generating item score (item1-item5) until the diff variable equals zero.
If I'm understanding correctly, you could loop something like the following (after setting all the items to initial values of 1, since possible values are 1 to 5):
capture generate rand_int = 0
replace rand_int = floor( 5 * runiform() + 1 ) // random int, 1 to 5
capture generate cnd = 0
forvalues k = 1(1)5 {
replace cnd = rand_int == `k' & sum_item < y & item`k' < 6
replace item`k' = item`k' + 1 if cnd
}
replace sum_item = item1+item2+item3+item4+item5
In words, that says is that if sum_item < y, then randomly add 1 to one of the items (as long as that item is not already equal to 5), and then you would keep doing it until sum_item == y for all rows.
So that's going to converge in roughly 20 iterations if the max value of y is 25 and items are from 1 to 5. I say "roughly" because there is a little waste in here when you add 1 to an item that is already equal to 5. You could ad some extra code for that, but I wouldn't bother if this is fast enough. E.g. for high values of item_sum it would be more efficient to start with initial values of 5 and randomly subtract 1 until it converges.
I'm not enough of a statistician to say that's the best or even an adequate way to do it, but intuitively to me it seems OK if you want a fairly uniform distribution of values. If you wanted the modal value to be 4, for example, that's a lot harder and not really a programming question any longer.

Excel Sum values by extracting numbers from single multi-line cell

AL-CHE-P1-1518 --- 270
AL-CHE-P2-1318 --- 280
AL-MAT-P1-1218 --- 280
AL-MAT-P4-0918 --- 40
all these data are inside same cell C2, my aim is to derive a formula to sum
270+280+280+40
in cell D2
tried regextract(c2,"\d(.*)\n") but only the first "270" is extracted, I need help, searched through all forums, couldn't get exact match, it will save me huge time if anyone could give me some hint on how to derive the sum inside same cell string
As far as I know, you can only accomplish this via a UDF:
Function ReturnSum(rng As Range) As Long
Dim arr As Variant
arr = Split(rng.Value, Chr(10) & Chr(10))
For i = 0 To UBound(arr)
ReturnSum = ReturnSum + Trim(Split(arr(i), " --- ")(1))
Next i
End Function
=SUMPRODUCT(ARRAYFORMULA(REGEXEXTRACT(SPLIT(C2,CHAR(10))," \d+")))
In Excel the formula is a bit more complicated and an array formula:
=SUM(IFERROR(--MID(TRIM(MID(SUBSTITUTE(A1,CHAR(10),REPT(" ",99)),(ROW($XFD$1:INDEX(XFD:XFD,LEN(A1)-LEN(SUBSTITUTE(A1,CHAR(10),""))+1))-1)*99+1,99)),FIND("---",TRIM(MID(SUBSTITUTE(A1,CHAR(10),REPT(" ",99)),(ROW($XFD$1:INDEX(XFD:XFD,LEN(A1)-LEN(SUBSTITUTE(A1,CHAR(10),""))+1))-1)*99+1,99)))+3,99),0))
Being an array formula it must be confirmed with Ctrl-Shift-Enter instead of Enter when Exiting Edit mode.

Need help implementing a certain logic that will fill a text to a certain width.

The task is to justify text within a certain width.
user inputs: Hello my name is Harrry. This is a sample text input that nobody
will enter.
output: What text width do you want?
user inputs: 15
output: |Hello my name|
|is Harrry. This|
|is a sample|
|text that|
|nobody will|
|enter. |
Basically, the line has to be 15 spaces wide including blank spaces. Also, if the next word in the line cant fit into 15, it will skip entirely. If there are multiple words in a line, it will try to distribute the spaces evenly between each word. See the line that says "Is a sample" for example.
I created a vector using getline(...) and all that and the entire text is saved in a vector. However, I'm kind of stuck on moving forward. I tried using multiple for loops, but I just cant seem to skip lines or even out the spacing at all.
Again, not looking or expecting anyone to solve this, but I'd appreciate it if you could guide me into the right direction in terms of logic/algorithm i should think about.
You should consider this Dynamic programming solution.
Split text into “good” lines
Since we don't know where we need to break the line for good justification, we start guessing where the break to be done to the paragraph. (That is we guess to determine whether we should break between two words and make the second word as start of the next line).
You notice something? We brutefore!
And note that if we can't find a word small enought to fit in the remaining space in the current line, we insert spaces inbetween the words in the current line. So, the space in the current line depends on the words that might go into the next or previous line. That's Dependency!
You are bruteforcing and you have dependency,there comes the DP!
Now lets define a state to identify the position on our path to solve this problem.
State: [i : j] ,which denotes line of words from ith word to jth word in the original sequence of words given as input.
Now, that you have state for the problem let us try to define how these states are related.
Since all our sub-problem states are just a pile of words, we can't just compare the words in each state and determine which one is better. Here better delineates to the use of line's width to hold maximum character and minimum spaces between the words in the particular line. So, we define a parameter, that would measure the goodness of the list of words from ith to jth words to make a line. (recall our definition of subproblem state). This is basically evaluating each of our subproblem state.
A simple comparison factor would be :
Define badness(i, j) for line of words[i : j].
For example,
Infinity if total length > page width,
else (page width − total length of words in current line)3
To make things even simple consider only suffix of the given text and apply this algorithm. This would reduce the DP table size from N*N to N.
So, For finishing lets make it clear what we want in DP terms,
subproblem = min. badness for suffix words[i :]
=⇒ No.of subproblems = Θ(n) where n = no of words
guessing = where to end first line, say i : j
=⇒ no. of choices for j = n − i = O(n)
recurrence relation between the subproblem:
• DP[i] = min(badness (i, j) + DP[j] for j in range (i + 1, n + 1))
• DP[n] = 0
=⇒ time per subproblem = Θ(n)
so, total time = Θ(n^2).
Also, I'll leave it to you how insert spaces between words after determining the words in each line.
Logic would be:
1) Put words in array
2) Loop though array of words
3) Count the number of chars in each word, and check until they are the text width or less (skip if more than textwidth). Remember the number of words that make up the total before going over 15 (example remember it took 3 words to get 9 characters, leaving space for 6 spaces)
4) Divide the number of spaces required by (number of words - 1)
5) Write those words, writing the same number of spaces each time.
Should give the desired effect I hope.
You obviously have some idea how to solve this, as you have already produced the sample output.
Perhaps re-solve your original problem writing down in words what you do in each step....
e.g.
Print text asking for sentence.
Take input
Split input into words.
Print text asking for width.
...
If you are stuck at any level, then expand the details into sub-steps.
I would look to separate the problem of working out a sequence of words which will fit onto a line.
Then how many spaces to add between each of the words.
Below is an example for printing one line after you find how many words to print and what is the starting word of the line.
std::cout << "|";
numOfSpaces = lineWidth - numOfCharsUsedByWords;
/*
* If we have three words |word1 word2 word3| in a line
* ideally the spaces to print between then are 1 less than the words
*/
int spaceChunks = numOfWordsInLine - 1;
/*
* Print the words from starting point to num of words
* you can print in a line
*/
for (j = 0; j < numOfWordsInLine; ++j) {
/*
* Calculation for the number of spaces to print
* after every word
*/
int spacesToPrint = 0;
if (spaceChunks <= 1) {
/*
* if one/two words then one
* chunk of spaces between so fill then up
*/
spacesToPrint = numOfSpaces;
} else {
/*
* Here its just segmenting a number into chunks
* example: segment 7 into 3 parts, will become 3 + 2 + 2
* 7 to 3 = (7%3) + (7/3) = 1 + 2 = 3
* 4 to 2 = (4%2) + (4/2) = 0 + 2 = 2
* 2 to 1 = (2%1) + (2/1) = 0 + 2 = 2
*/
spacesToPrint = (numOfSpaces % spaceChunks) + (numOfSpaces / spaceChunks);
}
numOfSpaces -= spacesToPrint;
spaceChunks--;
cout << words[j + lineStartIdx];
for (int space = 0; space < spacesToPrint; space++) {
std::cout << " ";
}
}
std::cout << "|" << std::endl;
Hope this code helps. Also you need to consider what happens if you set width less then the max word size.