In September 2024 Steve Kirsch published a spreadsheet for data from
Connecticut that contains rows for a total of about 500,000 people who
were enrolled on Medicare:
https://
Kirsch obfuscated the vaccine brand names in his spreadsheet in order to do his ChatGPT analysis, but this code converts the spreadsheet to a CSV file with unobfuscated vaccine brand names, and it also converts the dates to the ISO format and makes column names shorter:
download.file( " https:// www. skirsch. com/ covid/ ct_ mortality. xlsx", " ct_ mortality. xlsx") t=data. table( readxl:: read_ excel( " ct_ mortality. xlsx")) t[ BRAND==" PURPLE", BRAND: =" Pfizer"] t[ BRAND==" MIXED", BRAND: =" Moderna"] t[ BRAND==" CHERRY", BRAND: =" Janssen"] t[ BRAND==" MODERNA", BRAND: =" Moderna"] # the last two rows for Moderna were accidentally not obfuscated o=t[,.(id=PERSON_ ID, sex=Sex, dead=as. Date(` Date of death`), brand=BRAND, date1=as. Date( SHOTDATE_ 1), date2=as. Date( SHOTDATE_ 2), date3=as. Date( SHOTDATE_ 3), age=AGE_ AT_ DOSE1)] fwrite( o, " ctmort. csv. gz", na=" ")
I uploaded the output here:
f/
The following script generates a file for the Connecticut data
similar to the files generated by Kirsch's buckets.
script. The file shows the number of deaths and person-days grouped by
the month of vaccination, ongoing month, weeks since vaccination, dose
number, age, sex, and vaccine type. I assigned a random birthday to each
person in order to account for the aging of people over time with daily
precision:
library(data. table); library( lubridate) # fast way to get difference in floored years for a pair of dates after 1900 and before 2100 age=\(x, y){ class( x) =class( y) =NULL;( y- x-( y- 789)%/% 1461+( x- 789)%/% 1461)%/% 365} ct=fread( " http:// sars2. net/ f/ ctmort. csv. gz") # exclude 30 people whose date of death is before the first dose ct=ct[is. na( dead)| dead> =date1] mindate=as. Date( " 2020- 12- 1"); maxdate=as. Date( " 2024- 07- 31") t=ct[,.( id, sex, dead, type=brand, date=c( date1, date2, date3), dose=rep( 1: 3, each=. N), age)] t$ vaxmonth=substr( t$ date, 1, 7) set. seed( 0); t$ birth=as. Date( t$ date)- years( t$ age)- sample( 0: 364, nrow( t), T) buck=data. table() for( day in as. list( seq( mindate, maxdate, 1))){ cat( as. character( day), "\ n") ## buck=rbind( buck, unique( t[ date< =day&( is. na( dead)| day< =dead) & day> =birth], by=" id")[,.( # remove under earlier doses buck=rbind(buck, t[ date< =day&( is. na( dead)| day< =dead) & day> =birth][,.( # keep under earlier doses month=substr(day, 1, 7), vaxmonth, week=as. numeric( day- date)%/% 7, age=age( birth, day), dose, type, sex, alive=1, dead=dead==day)])[,.( alive=sum( alive), dead=sum( dead, na. rm=T)), by=.( month, vaxmonth, week, age, dose, type, sex)] } setorder( buck, month, vaxmonth, week, age, dose, type, sex) fwrite( buck, " ctbucketskeep. csv. gz", quote=F)
I uploaded the output here:
f/
Medicare is managed by the U.S. Department of Health and Human
Services (HHS). The website of HHS says:
"Generally, Medicare is for people 65 or older. You
may be able to get Medicare earlier if you have a disability, End-Stage
Renal Disease (permanent kidney failure requiring
dialysis or a transplant), or ALS (also
called Lou Gehrig's disease)." [https://
>ct=fread( " http:// sars2. net/ f/ ctmort. csv. gz") > ct[,.( cmr=round( mean(! is. na( dead) & dead- date1< 365)* 1e5), people=. N),.( age=age%/% 5* 5)][ order( age)]| > print( r=F) age cmr people 10 0 2 15 0 1 20 621 483 25 190 1055 30 306 1633 35 934 2034 40 1163 2494 45 1333 3151 50 2436 5624 55 2675 9681 60 2988 14925 65 1169 121444 70 1724 113601 75 2911 87246 80 5014 56220 85 8739 35681 90 15787 19168 95 23483 5932 100 32071 792 105 41379 29 110 100000 1 115 100000 2 age cmr people
In my subsequent analysis in this HTML file, I have generally excluded ages below 65.
In Kirsch's analysis of the Czech record-level data, his main
argument why Moderna vaccinese were unsafe than Pfizer vaccines was that
when he calculated age-specific mortality rates during the first year
from the first dose, Moderna got about 1.3 higher mortality rate than
Pfizer across various age groups. However I pointed out to him that it
might have been due to some confounders he didn't adjust for in his
analysis. In the plot below where I calculated an age-normalized
Moderna-Pfizer mortality ratio in the Czech data, my total ratio for all
months of vaccination aggregated together was about 1.3 like in Kirsch's
analysis, but my ratio fell close to 1.0 among people who were
vaccinated in the fourth quarter of 2021: [czech2.
In the new Connecticut data Kirsch now got about 10% higher mortality
rate for Pfizer than Moderna, but he again attributed the difference to
a difference in vaccine safety, even though this time Pfizer got higher
mortality rates than Moderna. When someone asked Kirsch to explain why
his results were now different to the Czech data, Kirsch replied: "it's a QA issue. Moderna is more deadly, but the batches
are even a greater problem." [https://
Kirsch also posted this tweet: "This is in
Connecticut only. Other states had completely the opposite numbers and
it was statistically significant there as well." [https://
In the following code I calculated age-normalized mortality rates in the Connecticut data for each combination of vaccination month, ongoing month, and vaccine brand. And when I divided the rate for Moderna with the rate for Pfizer, the total ratio for all months of vaccination was about 0.79. Moderna got a higher rate among people who got the first dose in March, April, May, June, July, or September 2021, even though during other months the age-normalized rate was higher for Pfizer. So I think it shows that people who got Pfizer and Moderna vaccines had different profiles of confounders during different months of vaccination, even though I guess Kirsch might argue it was rather because some batches were more deadly than others:
library(data. table) kimi=\( x){ e=floor( log10( ifelse( x==0, 1, abs( x)))); e2=pmax( e, 0)%/% 3+ 1 x[] =ifelse( abs( x) < 10, round( x), paste0( round( x/ 1e3^( e2- 1), ifelse( e%% 3==0, 1, 0)), c( " ", " k", " M", " B", " T")[ e2])); x} type1=" Moderna"; type2=" Pfizer" b=fread( " http:// sars2. net/ f/ ctbucketskeep. csv. gz") a=b[ age> =65& dose==1,.( dead=sum( dead), alive=sum( alive)),.( type, month, vaxmonth, age=pmin( age, 100))] pop=fread( " http:// sars2. net/ f/ uspopdeadmonthly. csv") a=merge( a, pop[,.( month=date, age, base=dead/ persondays)])[, base: =base* alive] a=a[ month> =" 2020- 12" & vaxmonth> =" 2020- 12" & vaxmonth< =" 2021- 12"] a=rbind( a, a[,.( dead=sum( dead), alive=sum( alive), base=sum( base), month=" Total"),.( age, vaxmonth, type)]) a=rbind( a, a[,.( dead=sum( dead), alive=sum( alive), base=sum( base), vaxmonth=" Total"),.( age, month, type)]) a=a[,.( rat=sum( dead)/ sum( base), alive=sum( alive)),.( type, vaxmonth, month)] ar=tapply( a$ rat, a[, 1: 3], c) m1=ar[ type1,,]; m2=ar[ type2,,] m=( m1- m2)/ ifelse( m1> m2, m2, m1) disp=m1/ m2; disp=ifelse( disp> =10, sprintf( "%. 1f", disp), sprintf( "%. 2f", disp)) disp[ lower. tri( disp) & row( disp)! =nrow( disp)] =" " exp=. 9; m=abs( m)^ exp* sign( m) maxcolor=4^ exp m[ m==Inf] =maxcolor; m[ m==- Inf] =- maxcolor pheatmap:: pheatmap( m, filename=" mort. png", display_ numbers=disp, gaps_ col=ncol( m)- 1, gaps_ row=nrow( m)- 1, cluster_ rows=F, cluster_ cols=F, legend=F, cellwidth=19, cellheight=19, fontsize=9, fontsize_ number=8, border_ color=NA, na_ col=" white", number_ color=ifelse(! is. na( m) & abs( m) >. 5* maxcolor, " white", " black"), breaks=seq(- maxcolor, maxcolor,, 256),