Let knitr/kable display latex code for further editing (.Rmd file) - latex

Similar to a previous question, I have to convert the chunk of code I used to create a kableExtra table from a Rmarkdown file into pure LaTeX format in Overleaf. Unfortunately, I still have not understood how I can get the latex code by running the KableExtra table in the Rmd file.
The following is the YAML header:
---
[...]
output:
pdf_document: default
html_document:
---
the following is my code:
{r, results='asis', echo=FALSE}
res_kbl = kableExtra::kbl(merg, longtable=TRUE, booktabs = T, caption = "Table 1", digits = 2) %>%
kableExtra::kable_styling(latex_options = c("striped", "HOLD_position"), font_size = 10) %>%
kableExtra::add_header_above(c(" " = 1, "in Complete sample" = 2, "in Restricted sample" = 2, "MAJ" = 4, "MIN" = 4, "MAJ" = 4, "MIN" = 4)) %>%
kableExtra::add_header_above(c(" " = 1, "No. of funds" = 4, "Fund Size Complete sample (USD million nominal)" = 8, "Fund Size Restricted sample (USD million nominal)" = 8)) %>%
kableExtra::add_header_above(c(" " = 5, "Complete sample" = 8, "Restricted sample" = 8)) %>%
kableExtra::row_spec(row = nrow(merg) - 1, underline = T, extra_css = "border-bottom: 2px solid;")
My question: How can I get the Latex code for the res_kbl table I have created?
Any suggestion would be very much appreciated!

If I understand right, you want to get the LaTex code of the kable res_tbl.
In this case,
Specify format = "latex" in kableExtra::kbl() (or knit::kable())
Next, writeLines(res_kbl)
Instead, you don't need to assign res_kbl variable.
You can use additional pipe operator with writeLines().
The result of writeLines(res_kbl) will give the code you want. But the code can be complex because kableExtra package has so many functionalities.
In addition when using only writeLines(), you don't need asis part in the chunk option. However, comment option can be a problem if you want to use it in the final document not in the console. Set the comment as blank text in that chunk.

Related

question for dask output when using dask.array.map_overlap

I would like to use dask.array.map_overlap to deal with the scipy interpolation function. However, I keep meeting errors that I cannot understand and hoping someone can answer this to me.
Here is the error message I have received if I want to run .compute().
ValueError: could not broadcast input array from shape (1070,0) into shape (1045,0)
To resolve the issue, I started to use .to_delayed() to check each partition outputs, and this is what I found.
Following is my python code.
Step 1. Load netCDF file through Xarray, and then output to dask.array with chunk size (400,400)
df = xr.open_dataset('./Brazil Sentinal2 Tile/' + data_file +'.nc')
lon, lat = df['lon'].data, df['lat'].data
slon = da.from_array(df['lon'], chunks=(400,400))
slat = da.from_array(df['lat'], chunks=(400,400))
data = da.from_array(df.isel(band=0).__xarray_dataarray_variable__.data, chunks=(400,400))
Step 2. declare a function for da.map_overlap use
def sumsum2(lon,lat,data, hex_res=10):
hex_col = 'hex' + str(hex_res)
lon_max, lon_min = lon.max(), lon.min()
lat_max, lat_min = lat.max(), lat.min()
b = box(lon_min, lat_min, lon_max, lat_max, ccw=True)
b = transform(lambda x, y: (y, x), b)
b = mapping(b)
target_df = pd.DataFrame(h3.polyfill( b, hex_res), columns=[hex_col])
target_df['lat'] = target_df[hex_col].apply(lambda x: h3.h3_to_geo(x)[0])
target_df['lon'] = target_df[hex_col].apply(lambda x: h3.h3_to_geo(x)[1])
tlon, tlat = target_df[['lon','lat']].values.T
abc = lNDI(points=(lon.ravel(), lat.ravel()),
values= data.ravel())(tlon,tlat)
target_df['out'] = abc
print(np.stack([tlon, tlat, abc],axis=1).shape)
return np.stack([tlon, tlat, abc],axis=1)
Step 3. Apply the da.map_overlap
b = da.map_overlap(sumsum2, slon[:1200,:1200], slat[:1200,:1200], data[:1200,:1200], depth=10, trim=True, boundary=None, align_arrays=False, dtype='float64',
)
Step 4. Using to_delayed() to test output shape
print(b.to_delayed().flatten()[0].compute().shape, )
print(b.to_delayed().flatten()[1].compute().shape)
(1065, 3)
(1045, 0)
(1090, 3)
(1070, 0)
which is saying that the output from da.map_overlap is only outputting 1-D dimension ( which is (1045,0) and (1070,0) ), while in the da.map_overlap, the output I am preparing is 2-D dimension ( which is (1065,3) and (1090,3) ).
In addition, if I turn off the trim argument, which is
c = da.map_overlap(sumsum2,
slon[:1200,:1200],
slat[:1200,:1200],
data[:1200,:1200],
depth=10,
trim=False,
boundary=None,
align_arrays=False,
dtype='float64',
)
print(c.to_delayed().flatten()[0].compute().shape, )
print(c.to_delayed().flatten()[1].compute().shape)
The output becomes
(1065, 3)
(1065, 3)
(1090, 3)
(1090, 3)
This is saying that when trim=True, I cut out everything?
because...
#-- print out the values
b.to_delayed().flatten()[0].compute()[:10,:]
(1065, 3)
array([], shape=(1045, 0), dtype=float64)
while...
#-- print out the values
c.to_delayed().flatten()[0].compute()[:10,:]
array([[ -47.83683837, -18.98359832, 1395.01848583],
[ -47.8482856 , -18.99038681, 2663.68391094],
[ -47.82800624, -18.99207069, 1465.56517187],
[ -47.81897323, -18.97919009, 2769.91556363],
[ -47.82066663, -19.00712956, 1607.85927095],
[ -47.82696896, -18.97167714, 2110.7516765 ],
[ -47.81562653, -18.98302933, 2662.72112163],
[ -47.82176881, -18.98594465, 2201.83205114],
[ -47.84567 , -18.97512514, 1283.20631652],
[ -47.84343568, -18.97270783, 1282.92117225]])
Any thoughts for this?
Thank You.
I guess I got the answer. Please let me if I am wrong.
I am not allowing to use trim=True is because I change the shape of output array (after surfing the internet, I notice that the shape of output array should be the same with the shape of input array). Since I change the shape, the dask has no idea how to deal with it so it returns the empty array to me (weird).
Instead of using trim=False, since I didn't ask cutting-out the buffer zone, it is now okay to output the return values. (although I still don't know why the dask cannot concat the chunked array, but believe is also related to shape)
The solution is using delayed function on da.concatenate, which is
delayed(da.concatenate)([e.to_delayed().flatten()[idx] for idx in range(len(e.to_delayed().flatten()))])
In this case, we are not relying on the concat function in map_overlap but use our own concat to combine the outputs we want.

Trying to use add = True and I get an error message

I am Trying to use add = True and I get an error message. How can I do it?
This is my code
quadratcount(schools.pp)
plot(schools.sp, col = "red")
plot(quadratcount(schools.pp), add= T)`
and this is the error message I get
Error in (function (x, y = NULL, density = NULL, angle = 45, border = NULL, : plot.new has not been called yet
Looks like you made a simple typo: In the first plot command you write plot(schools.sp, col = "red"), where you probably meant plot(schools.pp, col = "red"). For future questions please provide a reproducible example where we can run each line including library(spatstat) and the definition of schools.pp etc. If you can't share your data just either:
use the first few points of your data
use a built-in dataset
generate artificial data

Passing greek letters as colnames to kable

I've been trying to name an R data frame columns with greek letters in order to call kable and get a latex output table with header names as these greek letters.
The result is that kable does not recognise column names as the way latex greek letters are written, or the arguments are not passing to the function in the correct format.
A <- t(as.data.frame(seq(1:4)))
colnames(A) <- c("$\\\\alpha$", "$\\\\beta$", "$\\\\delta$", "$\\\\gamma$")
A %>%
kable(.,"latex", escape = F, booktabs = T, linesep = "", align = "c")
Is there a way to do this propperly?
The best solution I,ve found so far is set column names of the data frame to NULL, and write the table headers form the knit options as follows:
A <- t(as.data.frame(seq(1:4)))
colnames(A) <- NULL
A %>%
kable(., "latex", escape = F, booktabs = T, linesep = "", align = "c") %>%
add_header_above(c("$\\\\alpha$", "$\\\\beta$", "$\\\\delta$", "$\\\\gamma$"))
But this way is quite messy and lacks of automation.
Finally I tried the following and it doesn't work too.
A <- t(as.data.frame(seq(1:4)))
A %>%
kable(., "latex", escape = F, booktabs = T, linesep = "", align = "c", col.names = c("$\alpha$", "$\beta$", "$\delta$", "$\gamma$"))
Thanks a lot.
PD: Here is the link to the issue on rmarkdown GitHub

Citing within an RMarkdown table

I am attempting to create a table which has citations built into the table. Here is a visual of what I am trying to achieve.
As far as I know you can only add footnotes in rowvars or colvars in kableExtra (love that package).
# Create a dataframe called df
Component <- c('N2','P3')
Latency <- c('150 to 200ms', '625 to 800ms')
Location <- c('FCz, Fz, Cz', 'Pz, Oz')
df <- data.frame(Component, Latency, Location)
Below is my attempt after reading through kableExtra's Git page
# Trying some code taken from the kableExtra guide
row.names(df) <- df$Component
df[1] <- NULL
dt_footnote <- df
names(dt_footnote)[1] <- paste0(names(dt_footnote)[2],
footnote_marker_symbol(1))
row.names(dt_footnote)[2] <- paste0(row.names(dt_footnote)[2],
footnote_marker_alphabet(1))
kable(dt_footnote, align = "c",
# Remember this escape = F
escape = F, "latex", longtable = T, booktabs = T, caption = "My Table Name") %>%
kable_styling(full_width = F) %>%
footnote(alphabet = "Jones, 2013",
symbol = "Footnote Symbol 1; ",
footnote_as_chunk = T)
But this code only works on the headers. The ultimate goal would be if I could use a BibTex reference such as #JonesFunctionalMixedEffectModels2013 such that the final part of the code would look like
footnote(alphabet = #davidsonFunctionalMixedEffectModels2009,
symbol = "Footnote Symbol 1; ", footnote_as_chunk = T)
Anyone have any ideas?
Thanks
What I did at the end was to generate a temporary table with pander, then copy the references' number manually to my kable
pander(
df,
caption = "Temporal",
style = "simple",
justify = "left")

Add a line feed to a python gimp 2.8.4 script

I have a Python Gimp script that works well, but have one issue:
When I need to place multiple lines on an image, I have to create two separate text layers.
#Sample of text parameter xml file
<txtLyrs>
<extra_txtLyr>
<extra_txtLyr txtLyrName="lblLayer6" LyrFontColor="WHITE" \
LyrFontName="Interstate-Bold Bold" LyrFontSize="15.0" txtLyrString=\
"Some Text" txtX="460" txtY="331" txtlyr_height="17" txtlyr_width="73" index="71" />
<extra_txtLyr txtLyrName="lblLayer5" LyrFontColor="WHITE" \
LyrFontName="Interstate-Bold Bold" LyrFontSize="8.0" txtLyrString=\
"Some Text [10][13] Really Long Text" txtX="676" txtY="144" txtlyr_height="9"\
txtlyr_width="95" index="70" />
<extra_txtLyr txtLyrName="lblLayer4" LyrFontColor="WHITE" \
LyrFontName="Interstate-Bold Bold" LyrFontSize="8.0" txtLyrString=\
"Some Text" txtX="676" txtY="130" txtlyr_height="9" txtlyr_width="125" index="69" />
<extra_txtLyr txtLyrName="lblLayer3" LyrFontColor="WHITE" \
LyrFontName="Interstate-Bold Bold" LyrFontSize="15.0" txtLyrString=\
"Some Text" txtX="678" txtY="331" txtlyr_height="17" txtlyr_width="72" index="68" />
</extra_txtLyrs>
</txtLyrs>
#Constants removed to make smaller block
#Helper function to read parameters from xml file
def get_extratxt_btn_params( active_name ):
active_dgm = active_name
extraTxtLayers = xmldoc.getElementsByTagName("txtLyrs")[0]
if active_dgm:
siteTxtLayers = xmldoc.getElementsByTagName("extra_txtLyr")[0]
extraButtonTxtLayers = siteTxtLayers.getElementsByTagName("extra_txtLyr")
else:
siteTxtLayers = xmldoc.getElementsByTagName("other_txtLyr")[0]
extraButtonTxtLayers = siteTxtLayers.getElementsByTagName("other_txtLyr")
extraTxtParms = {}
for lyrParm in extraButtonTxtLayers:
lyrParams = [ lyrParm.getAttribute("txtLyrName"), \
lyrParm.getAttribute("LyrFontName"), \
lyrParm.getAttribute("LyrFontSize"), lyrParm.getAttribute("txtLyrString"), \
lyrParm.getAttribute("LyrFontColor"), lyrParm.getAttribute("txtlyr_height"), \
lyrParm.getAttribute("txtlyr_width"), lyrParm.getAttribute("txtX"), \
lyrParm.getAttribute("txtY")]
extraTxtParms [lyrParm.getAttribute("index")] = lyrParams
return extraTxtParms
##**function called by GIMP to create text layers from xml file
def dgm_extratxtlyr_create(image, drawable, title_color, inactive_color, active_color, \
alarm_color, normal_color, active_diagram):
txtlyrdict = get_extratxt_params( active_diagram )
d_sorted_by_value = OrderedDict(sorted(txtlyrdict.items(), key=lambda x: x[1]))
for k, txtlyr in d_sorted_by_value.items():
#Assign Layer Text
txtlayerName = txtlyr[3]
#Assign Layer Font Name
font_name = txtlyr[1]
#Assign Font Size
font_size = txtlyr[2]
#Assign Text color RGB values for colors are predefined constants because
#tuples don't pass correctly from xml
if txtlyr[4] == "RED":
textcolor = alarm_color
elif txtlyr[4] == "WHITE":
textcolor = inactive_color
elif txtlyr[4] == "GREEN":
textcolor = normal_color
elif txtlyr[4] == "BLACK":
textcolor = active_color
#Assign Text X Coordinate
xloc = txtlyr[7]
#Assign Text Y Coordinate
yloc = txtlyr[8]
#Create the new text layer
temp_layer = pdb.gimp_text_layer_new(image, txtlayerName, font_name, font_size, 0)
#Add it to the image
pdb.gimp_image_add_layer(image,temp_layer,-1)
#Change the color of the text
pdb.gimp_text_layer_set_color(temp_layer,textcolor)
#Move the text to the proper location
pdb.gimp_layer_translate(temp_layer, xloc, yloc)
#Set the text justification
pdb.gimp_text_layer_set_justification(temp_layer, 0)
How can I tell GIMP to add line feeds to the text layers, when I know they are too long?
Just add "new line" characters in your text string, before calling pdb.gimp_text_layer_new, as appropriate.
Btw, the variable you are naming "txtlayerName" (considerations about variable naming style apart) is the actual Text Content of the layer - not just the layer name. It happens that GIMP's usually name text layers by its contents by default - the parameter taken by gimp_text_layer_add_new is the actual text content on the image. You could also consider using the more complete call : "pdb.gimp_text_fontname` instead- which already adds the layer to the image, at the offset you want.
As for inserting the new lines using Python code, it is as simple as using the powerful langage syntax and methods for string manipulation to do that. For example, prior to creating the layer, you could do a lot of things.
This snippet replaces spaces by new lines if the layer is more than 12 characters long, and cut arbitrarily at each 6 chars if there are no spaces. It is naive, but you can get the idea and fashion your code:
if len(txtlayerName) > 12:
if " " in txtlayerName:
txtlayerName = txtlayerName.replace(" ", "\n")
else:
textlayerName = "\n".join(txtlayerName[i:i+6] for i in range(0, len(txtlayerName), 6))
This snippet allows for longer lines, assumiong there are several words in each line -
let's suppose you want a max-width of 80 chars, and there are several white-space separated words in the text:
textwidth = 80
result = []
txtline = []
index = 0
for word in textlayerName.split():
if index + len(word) < textwidth:
txtline.append(word)
index += len(word)
else:
result.append(" ".join(txtline))
txtline = [word]
index = len(word)
textlayerName = "\n".join(result)
This answer is very irrelevant to the question asked but when you try to search for adding font weight or making the text bold, you also come to this page like me.
There's no REAL solution
There's no procedure like gimp_text_layer_set_bold(text_layer))
however there's a workaround i.e., change your font. For Example: Change your font from Sans-serif to Sans-serif Bold. I hope it helps a wandering soul.

Resources